diff --git a/README.md b/README.md
index 54882e5444..c045d4540f 100644
--- a/README.md
+++ b/README.md
@@ -557,8 +557,8 @@ user_consumer_limit_anonymous_access=100, In case isn't defined default value is
Te set up Rate Limiting in case of the authorized access use these endpoints:
-1. `GET ../management/consumers/CONSUMER_ID/consumer/call-limits` - Get Call Limits for a Consumer
-2. `PUT ../management/consumers/CONSUMER_ID/consumer/call-limits` - Set Call Limits for a Consumer
+1. `GET ../management/consumers/CONSUMER_ID/consumer/rate-limits` - Get Rate Limits for a Consumer
+2. `PUT ../management/consumers/CONSUMER_ID/consumer/rate-limits` - Set Rate Limits for a Consumer
In order to make it work edit your props file in next way:
diff --git a/completed_developments.md b/completed_developments.md
index 314d55f1a2..e6b8a46a9b 100644
--- a/completed_developments.md
+++ b/completed_developments.md
@@ -137,7 +137,7 @@ Consent
Consumer
- Get Call Limits for a Consumer
+ Get Rate Limits for a Consumer
Get Consumer
Get Consumers
Get Consumers (logged in User)
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 1564734f44..6351120068 100644
--- a/obp-api/src/main/scala/code/api/util/APIUtil.scala
+++ b/obp-api/src/main/scala/code/api/util/APIUtil.scala
@@ -3119,7 +3119,10 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{
} // Direct Login Deprecated i.e Authorization: DirectLogin token=eyJhbGciOiJIUzI1NiJ9.eyIiOiIifQ.Y0jk1EQGB4XgdqmYZUHT6potmH3mKj5mEaA9qrIXXWQ
else if (getPropsAsBoolValue("allow_direct_login", true) && hasDirectLoginHeader(cc.authReqHeaderField) && !url.contains("/my/logins/direct")) {
DirectLogin.getUserFromDirectLoginHeaderFuture(cc)
- } else if (getPropsAsBoolValue("allow_direct_login", true) &&
+ }
+ // Endpoint /my/logins/direct is onboarding endpoint for Direct Login Flow authentication
+ // You POST your credentials (username, password, and consumer key) to the DirectLogin endpoint and receive a token in return.
+ else if (getPropsAsBoolValue("allow_direct_login", true) &&
(has2021DirectLoginHeader(cc.requestHeaders) || hasDirectLoginHeader(cc.authReqHeaderField)) &&
url.contains("/my/logins/direct")) {
Future{(Empty, Some(cc))}
diff --git a/obp-api/src/main/scala/code/api/util/AfterApiAuth.scala b/obp-api/src/main/scala/code/api/util/AfterApiAuth.scala
index 0fc70591c1..13eae4fc40 100644
--- a/obp-api/src/main/scala/code/api/util/AfterApiAuth.scala
+++ b/obp-api/src/main/scala/code/api/util/AfterApiAuth.scala
@@ -96,38 +96,47 @@ object AfterApiAuth extends MdcLoggable{
* Please note that first source is the table RateLimiting and second is the table Consumer
*/
def checkRateLimiting(userIsLockedOrDeleted: Future[(Box[User], Option[CallContext])]): Future[(Box[User], Option[CallContext])] = {
- def getRateLimiting(consumerId: String, version: String, name: String): Future[Box[RateLimiting]] = {
+ def getActiveRateLimitings(consumerId: String): Future[List[RateLimiting]] = {
RateLimitingUtil.useConsumerLimits match {
- case true => RateLimitingDI.rateLimiting.vend.getByConsumerId(consumerId, version, name, Some(new Date()))
- case false => Future(Empty)
+ case true => RateLimitingDI.rateLimiting.vend.getActiveCallLimitsByConsumerIdAtDate(consumerId, new Date())
+ case false => Future(List.empty)
}
}
+
+ def aggregateLimits(limits: List[RateLimiting], consumerId: String): CallLimit = {
+ def sumLimits(values: List[Long]): Long = {
+ val positiveValues = values.filter(_ > 0)
+ if (positiveValues.isEmpty) -1 else positiveValues.sum
+ }
+
+ if (limits.nonEmpty) {
+ CallLimit(
+ consumerId,
+ limits.find(_.apiName.isDefined).flatMap(_.apiName),
+ limits.find(_.apiVersion.isDefined).flatMap(_.apiVersion),
+ limits.find(_.bankId.isDefined).flatMap(_.bankId),
+ sumLimits(limits.map(_.perSecondCallLimit)),
+ sumLimits(limits.map(_.perMinuteCallLimit)),
+ sumLimits(limits.map(_.perHourCallLimit)),
+ sumLimits(limits.map(_.perDayCallLimit)),
+ sumLimits(limits.map(_.perWeekCallLimit)),
+ sumLimits(limits.map(_.perMonthCallLimit))
+ )
+ } else {
+ CallLimit(consumerId, None, None, None, -1, -1, -1, -1, -1, -1)
+ }
+ }
+
for {
(user, cc) <- userIsLockedOrDeleted
consumer = cc.flatMap(_.consumer)
- version = cc.map(_.implementedInVersion).getOrElse("None") // Calculate apiVersion in case of Rate Limiting
- operationId = cc.flatMap(_.operationId) // Unique Identifier of Dynamic Endpoints
- // Calculate apiName in case of Rate Limiting
- name = cc.flatMap(_.resourceDocument.map(_.partialFunctionName)) // 1st try: function name at resource doc
- .orElse(operationId) // 2nd try: In case of Dynamic Endpoint we can only use operationId
- .getOrElse("None") // Not found any unique identifier
- rateLimiting <- getRateLimiting(consumer.map(_.consumerId.get).getOrElse(""), version, name)
+ consumerId = consumer.map(_.consumerId.get).getOrElse("")
+ rateLimitings <- getActiveRateLimitings(consumerId)
} yield {
- val limit: Option[CallLimit] = rateLimiting match {
- case Full(rl) => Some(CallLimit(
- rl.consumerId,
- rl.apiName,
- rl.apiVersion,
- rl.bankId,
- rl.perSecondCallLimit,
- rl.perMinuteCallLimit,
- rl.perHourCallLimit,
- rl.perDayCallLimit,
- rl.perWeekCallLimit,
- rl.perMonthCallLimit))
- case Empty =>
+ val limit: Option[CallLimit] = rateLimitings match {
+ case Nil => // No rate limiting records found, use consumer defaults
Some(CallLimit(
- consumer.map(_.consumerId.get).getOrElse(""),
+ consumerId,
None,
None,
None,
@@ -138,7 +147,8 @@ object AfterApiAuth extends MdcLoggable{
consumer.map(_.perWeekCallLimit.get).getOrElse(-1),
consumer.map(_.perMonthCallLimit.get).getOrElse(-1)
))
- case _ => None
+ case activeLimits => // Aggregate multiple rate limiting records
+ Some(aggregateLimits(activeLimits, consumerId))
}
(user, cc.map(_.copy(rateLimiting = limit)))
}
diff --git a/obp-api/src/main/scala/code/api/util/ApiRole.scala b/obp-api/src/main/scala/code/api/util/ApiRole.scala
index d07208a039..c711c22633 100644
--- a/obp-api/src/main/scala/code/api/util/ApiRole.scala
+++ b/obp-api/src/main/scala/code/api/util/ApiRole.scala
@@ -480,15 +480,18 @@ object ApiRole extends MdcLoggable{
case class CanReadUserLockedStatus(requiresBankId: Boolean = false) extends ApiRole
lazy val canReadUserLockedStatus = CanReadUserLockedStatus()
- case class CanSetCallLimits(requiresBankId: Boolean = false) extends ApiRole
- lazy val canSetCallLimits = CanSetCallLimits()
+ case class CanUpdateRateLimits(requiresBankId: Boolean = false) extends ApiRole
+ lazy val canUpdateRateLimits = CanUpdateRateLimits()
+
+ case class CanCreateRateLimits(requiresBankId: Boolean = false) extends ApiRole
+ lazy val canCreateRateLimits = CanCreateRateLimits()
case class CanDeleteRateLimiting(requiresBankId: Boolean = false) extends ApiRole
- lazy val canDeleteRateLimiting = CanDeleteRateLimiting()
-
+ lazy val canDeleteRateLimits = CanDeleteRateLimiting()
+
case class CanCreateCustomerMessage(requiresBankId: Boolean = true) extends ApiRole
- lazy val canCreateCustomerMessage = CanCreateCustomerMessage()
-
+ lazy val canCreateCustomerMessage = CanCreateCustomerMessage()
+
case class CanGetCustomerMessages(requiresBankId: Boolean = true) extends ApiRole
lazy val canGetCustomerMessages = CanGetCustomerMessages()
@@ -503,10 +506,10 @@ object ApiRole extends MdcLoggable{
case class CanCreateSystemAccountNotificationWebhook(requiresBankId: Boolean = false) extends ApiRole
lazy val canCreateSystemAccountNotificationWebhook = CanCreateSystemAccountNotificationWebhook()
-
+
case class CanCreateAccountNotificationWebhookAtOneBank(requiresBankId: Boolean = true) extends ApiRole
lazy val canCreateAccountNotificationWebhookAtOneBank = CanCreateAccountNotificationWebhookAtOneBank()
-
+
case class CanUpdateWebhook(requiresBankId: Boolean = true) extends ApiRole
lazy val canUpdateWebhook = CanUpdateWebhook()
@@ -551,22 +554,22 @@ object ApiRole extends MdcLoggable{
case class CanUpdateProductAttribute(requiresBankId: Boolean = true) extends ApiRole
lazy val canUpdateProductAttribute = CanUpdateProductAttribute()
-
+
case class CanUpdateBankAttribute(requiresBankId: Boolean = true) extends ApiRole
- lazy val canUpdateBankAttribute = CanUpdateBankAttribute()
-
+ lazy val canUpdateBankAttribute = CanUpdateBankAttribute()
+
case class CanUpdateAtmAttribute(requiresBankId: Boolean = true) extends ApiRole
- lazy val canUpdateAtmAttribute = CanUpdateAtmAttribute()
-
+ lazy val canUpdateAtmAttribute = CanUpdateAtmAttribute()
+
case class CanUpdateAtmAttributeAtAnyBank(requiresBankId: Boolean = false) extends ApiRole
lazy val canUpdateAtmAttributeAtAnyBank = CanUpdateAtmAttributeAtAnyBank()
-
+
case class CanGetBankAttribute(requiresBankId: Boolean = true) extends ApiRole
- lazy val canGetBankAttribute = CanGetBankAttribute()
-
+ lazy val canGetBankAttribute = CanGetBankAttribute()
+
case class CanGetAtmAttribute(requiresBankId: Boolean = true) extends ApiRole
- lazy val canGetAtmAttribute = CanGetAtmAttribute()
-
+ lazy val canGetAtmAttribute = CanGetAtmAttribute()
+
case class CanGetAtmAttributeAtAnyBank(requiresBankId: Boolean = false) extends ApiRole
lazy val canGetAtmAttributeAtAnyBank = CanGetAtmAttributeAtAnyBank()
@@ -575,25 +578,25 @@ object ApiRole extends MdcLoggable{
case class CanDeleteProductAttribute(requiresBankId: Boolean = true) extends ApiRole
lazy val canDeleteProductAttribute = CanDeleteProductAttribute()
-
+
case class CanDeleteBankAttribute(requiresBankId: Boolean = true) extends ApiRole
- lazy val canDeleteBankAttribute = CanDeleteBankAttribute()
-
+ lazy val canDeleteBankAttribute = CanDeleteBankAttribute()
+
case class CanDeleteAtmAttribute(requiresBankId: Boolean = true) extends ApiRole
lazy val canDeleteAtmAttribute = CanDeleteAtmAttribute()
-
+
case class CanDeleteAtmAttributeAtAnyBank(requiresBankId: Boolean = false) extends ApiRole
lazy val canDeleteAtmAttributeAtAnyBank = CanDeleteAtmAttributeAtAnyBank()
case class CanCreateProductAttribute(requiresBankId: Boolean = true) extends ApiRole
lazy val canCreateProductAttribute = CanCreateProductAttribute()
-
+
case class CanCreateBankAttribute(requiresBankId: Boolean = true) extends ApiRole
lazy val canCreateBankAttribute = CanCreateBankAttribute()
-
+
case class CanCreateAtmAttribute(requiresBankId: Boolean = true) extends ApiRole
- lazy val canCreateAtmAttribute = CanCreateAtmAttribute()
-
+ lazy val canCreateAtmAttribute = CanCreateAtmAttribute()
+
case class CanCreateAtmAttributeAtAnyBank(requiresBankId: Boolean = false) extends ApiRole
lazy val canCreateAtmAttributeAtAnyBank = CanCreateAtmAttributeAtAnyBank()
@@ -608,7 +611,7 @@ object ApiRole extends MdcLoggable{
case class CanCreateProductFee(requiresBankId: Boolean = true) extends ApiRole
lazy val canCreateProductFee = CanCreateProductFee()
-
+
case class CanMaintainProductCollection(requiresBankId: Boolean = true) extends ApiRole
lazy val canMaintainProductCollection = CanMaintainProductCollection()
@@ -669,10 +672,10 @@ object ApiRole extends MdcLoggable{
case class CanCreateBankLevelDynamicEntity(requiresBankId: Boolean = true) extends ApiRole
lazy val canCreateBankLevelDynamicEntity = CanCreateBankLevelDynamicEntity()
-
+
case class CanUpdateSystemLevelDynamicEntity(requiresBankId: Boolean = false) extends ApiRole
lazy val canUpdateSystemDynamicEntity = CanUpdateSystemLevelDynamicEntity()
-
+
case class CanUpdateBankLevelDynamicEntity(requiresBankId: Boolean = true) extends ApiRole
lazy val canUpdateBankLevelDynamicEntity = CanUpdateBankLevelDynamicEntity()
@@ -687,13 +690,13 @@ object ApiRole extends MdcLoggable{
case class CanGetDynamicEndpoint(requiresBankId: Boolean = false) extends ApiRole
lazy val canGetDynamicEndpoint = CanGetDynamicEndpoint()
-
+
case class CanGetDynamicEndpoints(requiresBankId: Boolean = false) extends ApiRole
lazy val canGetDynamicEndpoints = CanGetDynamicEndpoints()
case class CanGetBankLevelDynamicEndpoint(requiresBankId: Boolean = true) extends ApiRole
lazy val canGetBankLevelDynamicEndpoint = CanGetBankLevelDynamicEndpoint()
-
+
case class CanGetBankLevelDynamicEndpoints(requiresBankId: Boolean = true) extends ApiRole
lazy val canGetBankLevelDynamicEndpoints = CanGetBankLevelDynamicEndpoints()
@@ -714,7 +717,7 @@ object ApiRole extends MdcLoggable{
case class CanDeleteBankLevelDynamicEndpoint(requiresBankId: Boolean = true) extends ApiRole
lazy val canDeleteBankLevelDynamicEndpoint = CanDeleteBankLevelDynamicEndpoint()
-
+
case class CanCreateResetPasswordUrl(requiresBankId: Boolean = false) extends ApiRole
lazy val canCreateResetPasswordUrl = CanCreateResetPasswordUrl()
@@ -744,7 +747,7 @@ object ApiRole extends MdcLoggable{
case class CanCreateDirectDebitAtOneBank(requiresBankId: Boolean = true) extends ApiRole
lazy val canCreateDirectDebitAtOneBank = CanCreateDirectDebitAtOneBank()
-
+
case class CanCreateStandingOrderAtOneBank(requiresBankId: Boolean = true) extends ApiRole
lazy val canCreateStandingOrderAtOneBank = CanCreateStandingOrderAtOneBank()
@@ -762,7 +765,7 @@ object ApiRole extends MdcLoggable{
case class CanDeleteCustomerAttributeAtOneBank(requiresBankId: Boolean = true) extends ApiRole
lazy val canDeleteCustomerAttributeAtOneBank = CanDeleteCustomerAttributeAtOneBank()
-
+
case class CanDeleteCustomerAttributeAtAnyBank(requiresBankId: Boolean = false) extends ApiRole
lazy val canDeleteCustomerAttributeAtAnyBank = CanDeleteCustomerAttributeAtAnyBank()
@@ -810,61 +813,61 @@ object ApiRole extends MdcLoggable{
case class CanGetDoubleEntryTransactionAtOneBank(requiresBankId: Boolean = true) extends ApiRole
lazy val canGetDoubleEntryTransactionAtOneBank = CanGetDoubleEntryTransactionAtOneBank()
-
+
case class CanGetDoubleEntryTransactionAtAnyBank(requiresBankId: Boolean = false) extends ApiRole
lazy val canGetDoubleEntryTransactionAtAnyBank = CanGetDoubleEntryTransactionAtAnyBank()
case class CanReadResourceDoc(requiresBankId: Boolean = false) extends ApiRole
lazy val canReadResourceDoc = CanReadResourceDoc()
-
+
case class CanReadStaticResourceDoc(requiresBankId: Boolean = false) extends ApiRole
lazy val canReadStaticResourceDoc = CanReadStaticResourceDoc()
-
+
case class CanReadDynamicResourceDocsAtOneBank(requiresBankId: Boolean = true) extends ApiRole
lazy val canReadDynamicResourceDocsAtOneBank = CanReadDynamicResourceDocsAtOneBank()
-
+
case class CanReadGlossary(requiresBankId: Boolean = false) extends ApiRole
lazy val canReadGlossary = CanReadGlossary()
case class CanCreateCustomerAttributeDefinitionAtOneBank(requiresBankId: Boolean = true) extends ApiRole
lazy val canCreateCustomerAttributeDefinitionAtOneBank = CanCreateCustomerAttributeDefinitionAtOneBank()
-
+
case class CanDeleteCustomerAttributeDefinitionAtOneBank(requiresBankId: Boolean = true) extends ApiRole
lazy val canDeleteCustomerAttributeDefinitionAtOneBank = CanDeleteCustomerAttributeDefinitionAtOneBank()
-
+
case class CanGetCustomerAttributeDefinitionAtOneBank(requiresBankId: Boolean = true) extends ApiRole
lazy val canGetCustomerAttributeDefinitionAtOneBank = CanGetCustomerAttributeDefinitionAtOneBank()
-
+
case class CanCreateAccountAttributeDefinitionAtOneBank(requiresBankId: Boolean = true) extends ApiRole
- lazy val canCreateAccountAttributeDefinitionAtOneBank = CanCreateAccountAttributeDefinitionAtOneBank()
-
+ lazy val canCreateAccountAttributeDefinitionAtOneBank = CanCreateAccountAttributeDefinitionAtOneBank()
+
case class CanDeleteAccountAttributeDefinitionAtOneBank(requiresBankId: Boolean = true) extends ApiRole
lazy val canDeleteAccountAttributeDefinitionAtOneBank = CanDeleteAccountAttributeDefinitionAtOneBank()
-
+
case class CanGetAccountAttributeDefinitionAtOneBank(requiresBankId: Boolean = true) extends ApiRole
- lazy val canGetAccountAttributeDefinitionAtOneBank = CanGetAccountAttributeDefinitionAtOneBank()
-
+ lazy val canGetAccountAttributeDefinitionAtOneBank = CanGetAccountAttributeDefinitionAtOneBank()
+
case class CanDeleteProductAttributeDefinitionAtOneBank(requiresBankId: Boolean = true) extends ApiRole
- lazy val canDeleteProductAttributeDefinitionAtOneBank = CanDeleteProductAttributeDefinitionAtOneBank()
-
+ lazy val canDeleteProductAttributeDefinitionAtOneBank = CanDeleteProductAttributeDefinitionAtOneBank()
+
case class CanGetProductAttributeDefinitionAtOneBank(requiresBankId: Boolean = true) extends ApiRole
lazy val canGetProductAttributeDefinitionAtOneBank = CanGetProductAttributeDefinitionAtOneBank()
-
+
case class CanCreateProductAttributeDefinitionAtOneBank(requiresBankId: Boolean = true) extends ApiRole
lazy val canCreateProductAttributeDefinitionAtOneBank = CanCreateProductAttributeDefinitionAtOneBank()
-
+
case class CanCreateBankAttributeDefinitionAtOneBank(requiresBankId: Boolean = true) extends ApiRole
lazy val canCreateBankAttributeDefinitionAtOneBank = CanCreateBankAttributeDefinitionAtOneBank()
-
+
case class CanCreateTransactionAttributeDefinitionAtOneBank(requiresBankId: Boolean = true) extends ApiRole
lazy val canCreateTransactionAttributeDefinitionAtOneBank = CanCreateTransactionAttributeDefinitionAtOneBank()
-
+
case class CanDeleteTransactionAttributeDefinitionAtOneBank(requiresBankId: Boolean = true) extends ApiRole
lazy val canDeleteTransactionAttributeDefinitionAtOneBank = CanDeleteTransactionAttributeDefinitionAtOneBank()
-
+
case class CanGetTransactionAttributeDefinitionAtOneBank(requiresBankId: Boolean = true) extends ApiRole
- lazy val canGetTransactionAttributeDefinitionAtOneBank = CanGetTransactionAttributeDefinitionAtOneBank()
-
+ lazy val canGetTransactionAttributeDefinitionAtOneBank = CanGetTransactionAttributeDefinitionAtOneBank()
+
case class CanCreateTransactionRequestAttributeDefinitionAtOneBank(requiresBankId: Boolean = true) extends ApiRole
lazy val canCreateTransactionRequestAttributeDefinitionAtOneBank = CanCreateTransactionRequestAttributeDefinitionAtOneBank()
@@ -882,19 +885,19 @@ object ApiRole extends MdcLoggable{
case class CanCreateCardAttributeDefinitionAtOneBank(requiresBankId: Boolean = true) extends ApiRole
lazy val canCreateCardAttributeDefinitionAtOneBank = CanCreateCardAttributeDefinitionAtOneBank()
-
+
case class CanDeleteTransactionCascade(requiresBankId: Boolean = true) extends ApiRole
lazy val canDeleteTransactionCascade = CanDeleteTransactionCascade()
-
+
case class CanDeleteAccountCascade(requiresBankId: Boolean = true) extends ApiRole
- lazy val canDeleteAccountCascade = CanDeleteAccountCascade()
-
+ lazy val canDeleteAccountCascade = CanDeleteAccountCascade()
+
case class CanDeleteBankCascade(requiresBankId: Boolean = true) extends ApiRole
lazy val canDeleteBankCascade = CanDeleteBankCascade()
-
+
case class CanDeleteProductCascade(requiresBankId: Boolean = true) extends ApiRole
- lazy val canDeleteProductCascade = CanDeleteProductCascade()
-
+ lazy val canDeleteProductCascade = CanDeleteProductCascade()
+
case class CanDeleteCustomerCascade(requiresBankId: Boolean = true) extends ApiRole
lazy val canDeleteCustomerCascade = CanDeleteCustomerCascade()
@@ -933,10 +936,10 @@ object ApiRole extends MdcLoggable{
case class CanUpdateConnectorMethod(requiresBankId: Boolean = false) extends ApiRole
lazy val canUpdateConnectorMethod = CanUpdateConnectorMethod()
-
+
case class CanGetAllConnectorMethods(requiresBankId: Boolean = false) extends ApiRole
lazy val canGetAllConnectorMethods = CanGetAllConnectorMethods()
-
+
case class CanCreateDynamicResourceDoc(requiresBankId: Boolean = false) extends ApiRole
lazy val canCreateDynamicResourceDoc = CanCreateDynamicResourceDoc()
@@ -951,7 +954,7 @@ object ApiRole extends MdcLoggable{
case class CanDeleteDynamicResourceDoc(requiresBankId: Boolean = false) extends ApiRole
lazy val canDeleteDynamicResourceDoc = CanDeleteDynamicResourceDoc()
-
+
case class CanCreateBankLevelDynamicResourceDoc(requiresBankId: Boolean = true) extends ApiRole
lazy val canCreateBankLevelDynamicResourceDoc = CanCreateBankLevelDynamicResourceDoc()
@@ -969,7 +972,7 @@ object ApiRole extends MdcLoggable{
case class CanCreateDynamicMessageDoc(requiresBankId: Boolean = false) extends ApiRole
lazy val canCreateDynamicMessageDoc = CanCreateDynamicMessageDoc()
-
+
case class CanCreateBankLevelDynamicMessageDoc(requiresBankId: Boolean = true) extends ApiRole
lazy val canCreateBankLevelDynamicMessageDoc = CanCreateBankLevelDynamicMessageDoc()
@@ -1020,21 +1023,21 @@ object ApiRole extends MdcLoggable{
case class CanDeleteBankLevelEndpointMapping(requiresBankId: Boolean = true) extends ApiRole
lazy val canDeleteBankLevelEndpointMapping = CanDeleteBankLevelEndpointMapping()
-
+
case class CanCreateUserInvitation(requiresBankId: Boolean = true) extends ApiRole
- lazy val canCreateUserInvitation = CanCreateUserInvitation()
+ lazy val canCreateUserInvitation = CanCreateUserInvitation()
case class CanGetUserInvitation(requiresBankId: Boolean = true) extends ApiRole
lazy val canGetUserInvitation = CanGetUserInvitation()
case class CanCreateSystemLevelEndpointTag(requiresBankId: Boolean = false) extends ApiRole
lazy val canCreateSystemLevelEndpointTag = CanCreateSystemLevelEndpointTag()
-
+
case class CanUpdateSystemLevelEndpointTag(requiresBankId: Boolean = false) extends ApiRole
lazy val canUpdateSystemLevelEndpointTag = CanUpdateSystemLevelEndpointTag()
-
+
case class CanDeleteSystemLevelEndpointTag(requiresBankId: Boolean = false) extends ApiRole
lazy val canDeleteSystemLevelEndpointTag = CanDeleteSystemLevelEndpointTag()
-
+
case class CanGetSystemLevelEndpointTag(requiresBankId: Boolean = false) extends ApiRole
lazy val canGetSystemLevelEndpointTag = CanGetSystemLevelEndpointTag()
@@ -1071,7 +1074,7 @@ object ApiRole extends MdcLoggable{
case class CanGetAccountsMinimalForCustomerAtAnyBank(requiresBankId: Boolean = false) extends ApiRole
lazy val canGetAccountsMinimalForCustomerAtAnyBank = CanGetAccountsMinimalForCustomerAtAnyBank()
-
+
case class CanUpdateConsentStatusAtOneBank(requiresBankId: Boolean = true) extends ApiRole
lazy val canUpdateConsentStatusAtOneBank = CanUpdateConsentStatusAtOneBank()
case class CanUpdateConsentStatusAtAnyBank(requiresBankId: Boolean = false) extends ApiRole
@@ -1096,7 +1099,7 @@ object ApiRole extends MdcLoggable{
case class CanGetSystemIntegrity(requiresBankId: Boolean = false) extends ApiRole
lazy val canGetSystemIntegrity = CanGetSystemIntegrity()
-
+
private val dynamicApiRoles = new ConcurrentHashMap[String, ApiRole]
private case class DynamicApiRole(role: String, requiresBankId: Boolean = false) extends ApiRole{
@@ -1142,35 +1145,35 @@ object ApiRole extends MdcLoggable{
}
object Util {
-
+
def checkWrongDefinedNames: List[List[Unit]] = {
import scala.meta._
val source: Source = new java.io.File("obp-api/src/main/scala/code/api/util/ApiRole.scala").parse[Source].get
- val allowedPrefixes =
+ val allowedPrefixes =
List(
"CanCreate",
- "CanGet",
- "CanUpdate",
- "CanDelete",
- "CanMaintain",
- "CanSearch",
- "CanEnable",
+ "CanGet",
+ "CanUpdate",
+ "CanDelete",
+ "CanMaintain",
+ "CanSearch",
+ "CanEnable",
"CanDisable"
)
- val allowedExistingNames =
+ val allowedExistingNames =
List(
"CanQueryOtherUser",
- "CanAddSocialMediaHandle",
- "CanReadMetrics",
- "CanUseFirehoseAtAnyBank",
- "CanReadAggregateMetrics",
- "CanUnlockUser",
- "CanReadUserLockedStatus",
- "CanReadCallLimits",
- "CanCheckFundsAvailable",
- "CanRefreshUser",
- "CanReadFx",
+ "CanAddSocialMediaHandle",
+ "CanReadMetrics",
+ "CanUseFirehoseAtAnyBank",
+ "CanReadAggregateMetrics",
+ "CanUnlockUser",
+ "CanReadUserLockedStatus",
+ "CanReadCallLimits",
+ "CanCheckFundsAvailable",
+ "CanRefreshUser",
+ "CanReadFx",
"CanSetCallLimits",
"CanDeleteRateLimiting"
)
diff --git a/obp-api/src/main/scala/code/api/util/ApiSession.scala b/obp-api/src/main/scala/code/api/util/ApiSession.scala
index d6f5774911..71d60b9eca 100644
--- a/obp-api/src/main/scala/code/api/util/ApiSession.scala
+++ b/obp-api/src/main/scala/code/api/util/ApiSession.scala
@@ -12,6 +12,7 @@ import code.context.UserAuthContextProvider
import code.customer.CustomerX
import code.model.{Consumer, _}
import code.util.Helper.MdcLoggable
+import code.util.SecureLogging
import code.views.Views
import com.openbankproject.commons.model._
import com.openbankproject.commons.util.{EnumValue, OBPEnumeration}
@@ -56,7 +57,9 @@ case class CallContext(
paginationOffset : Option[String] = None,
paginationLimit : Option[String] = None
) extends MdcLoggable {
-
+ override def toString: String = SecureLogging.maskSensitive(
+ s"${this.getClass.getSimpleName}(${this.productIterator.mkString(", ")})"
+ )
//This is only used to connect the back adapter. not useful for sandbox mode.
def toOutboundAdapterCallContext: OutboundAdapterCallContext= {
for{
diff --git a/obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala b/obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala
index 283cb12640..abc3f17f47 100644
--- a/obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala
+++ b/obp-api/src/main/scala/code/api/v3_1_0/APIMethods310.scala
@@ -509,11 +509,11 @@ trait APIMethods310 {
nameOf(callsLimit),
"PUT",
"/management/consumers/CONSUMER_ID/consumer/call-limits",
- "Set Rate Limiting (call limits) per Consumer",
+ "Set Rate Limits (call limits) per Consumer",
s"""
|Set the API rate limiting (call limits) per Consumer:
|
- |Call limits can be set:
+ |Rate limits can be set:
|
|Per Second
|Per Minute
@@ -537,14 +537,14 @@ trait APIMethods310 {
UnknownError
),
List(apiTagConsumer),
- Some(List(canSetCallLimits)))
+ Some(List(canUpdateRateLimits)))
lazy val callsLimit : OBPEndpoint = {
case "management" :: "consumers" :: consumerId :: "consumer" :: "call-limits" :: Nil JsonPut json -> _ => {
cc => implicit val ec = EndpointContext(Some(cc))
for {
(Full(u), callContext) <- authenticatedAccess(cc)
- _ <- NewStyle.function.hasEntitlement("", u.userId, canSetCallLimits, callContext)
+ _ <- NewStyle.function.hasEntitlement("", u.userId, canUpdateRateLimits, callContext)
postJson <- NewStyle.function.tryons(s"$InvalidJsonFormat The Json body should be the $CallLimitPostJson ", 400, callContext) {
json.extract[CallLimitPostJson]
}
@@ -578,9 +578,9 @@ trait APIMethods310 {
nameOf(getCallsLimit),
"GET",
"/management/consumers/CONSUMER_ID/consumer/call-limits",
- "Get Call Limits for a Consumer",
+ "Get Rate Limits for a Consumer",
s"""
- |Get Calls limits per Consumer.
+ |Get Rate Limits per Consumer.
|${userAuthenticationMessage(true)}
|
|""".stripMargin,
@@ -596,7 +596,7 @@ trait APIMethods310 {
UnknownError
),
List(apiTagConsumer),
- Some(List(canSetCallLimits)))
+ Some(List(canUpdateRateLimits)))
diff --git a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala
index db729eb4ae..3f5b94eec0 100644
--- a/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala
+++ b/obp-api/src/main/scala/code/api/v4_0_0/APIMethods400.scala
@@ -202,14 +202,14 @@ trait APIMethods400 extends MdcLoggable {
UnknownError
),
List(apiTagConsumer, apiTagRateLimits),
- Some(List(canSetCallLimits)))
+ Some(List(canUpdateRateLimits)))
lazy val callsLimit : OBPEndpoint = {
case "management" :: "consumers" :: consumerId :: "consumer" :: "call-limits" :: Nil JsonPut json -> _ => {
cc => implicit val ec = EndpointContext(Some(cc))
for {
(Full(u), callContext) <- authenticatedAccess(cc)
- _ <- NewStyle.function.handleEntitlementsAndScopes("", u.userId, List(canSetCallLimits), callContext)
+ _ <- NewStyle.function.handleEntitlementsAndScopes("", u.userId, List(canUpdateRateLimits), callContext)
postJson <- NewStyle.function.tryons(s"$InvalidJsonFormat The Json body should be the $CallLimitPostJsonV400 ", 400, callContext) {
json.extract[CallLimitPostJsonV400]
}
@@ -3578,8 +3578,8 @@ trait APIMethods400 extends MdcLoggable {
|The user creating this will be automatically assigned the Role CanCreateEntitlementAtOneBank.
|Thus the User can manage the bank they create and assign Roles to other Users.
|
- |Only SANDBOX mode
- |The settlement accounts are created specified by the bank in the POST body.
+ |Only SANDBOX mode (i.e. when connector=mapped in properties file)
+ |The settlement accounts are automatically created by the system when the bank is created.
|Name and account id are created in accordance to the next rules:
| - Incoming account (name: Default incoming settlement account, Account ID: OBP_DEFAULT_INCOMING_ACCOUNT_ID, currency: EUR)
| - Outgoing account (name: Default outgoing settlement account, Account ID: OBP_DEFAULT_OUTGOING_ACCOUNT_ID, currency: EUR)
diff --git a/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala b/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala
index 9a23dac09e..f985b2402c 100644
--- a/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala
+++ b/obp-api/src/main/scala/code/api/v5_0_0/APIMethods500.scala
@@ -153,8 +153,8 @@ trait APIMethods500 {
|The user creating this will be automatically assigned the Role CanCreateEntitlementAtOneBank.
|Thus the User can manage the bank they create and assign Roles to other Users.
|
- |Only SANDBOX mode
- |The settlement accounts are created specified by the bank in the POST body.
+ |Only SANDBOX mode (i.e. when connector=mapped in properties file)
+ |The settlement accounts are automatically created by the system when the bank is created.
|Name and account id are created in accordance to the next rules:
| - Incoming account (name: Default incoming settlement account, Account ID: OBP_DEFAULT_INCOMING_ACCOUNT_ID, currency: EUR)
| - Outgoing account (name: Default outgoing settlement account, Account ID: OBP_DEFAULT_OUTGOING_ACCOUNT_ID, currency: EUR)
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 82bbbe2c4d..8805a93313 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
@@ -3329,8 +3329,8 @@ trait APIMethods510 {
implementedInApiVersion,
nameOf(getCallsLimit),
"GET",
- "/management/consumers/CONSUMER_ID/consumer/call-limits",
- "Get Call Limits for a Consumer",
+ "/management/consumers/CONSUMER_ID/consumer/rate-limits",
+ "Get Rate Limits for a Consumer",
s"""
|Get Calls limits per Consumer.
|${userAuthenticationMessage(true)}
@@ -3352,7 +3352,7 @@ trait APIMethods510 {
lazy val getCallsLimit: OBPEndpoint = {
- case "management" :: "consumers" :: consumerId :: "consumer" :: "call-limits" :: Nil JsonGet _ =>
+ case "management" :: "consumers" :: consumerId :: "consumer" :: "rate-limits" :: Nil JsonGet _ =>
cc =>
implicit val ec = EndpointContext(Some(cc))
for {
diff --git a/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala b/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala
index 4eb9a5bb3e..7eceafc774 100644
--- a/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala
+++ b/obp-api/src/main/scala/code/api/v6_0_0/APIMethods600.scala
@@ -11,6 +11,8 @@ import code.api.util.FutureUtil.EndpointContext
import code.api.util.NewStyle.HttpCode
import code.api.util.{APIUtil, ErrorMessages, NewStyle, RateLimitingUtil}
import code.api.v3_0_0.JSONFactory300
+import code.api.v4_0_0.CallLimitPostJsonV400
+import code.api.v4_0_0.JSONFactory400.createCallsLimitJson
import code.api.v5_0_0.JSONFactory500
import code.api.v6_0_0.JSONFactory600.{createActiveCallLimitsJsonV600, createCallLimitJsonV600, createCurrentUsageJson}
import code.bankconnectors.LocalMappedConnectorInternal
@@ -145,16 +147,16 @@ trait APIMethods600 {
(accountsJson, HttpCode.`200`(callContext))
}
}
-
+
staticResourceDocs += ResourceDoc(
getCurrentCallsLimit,
implementedInApiVersion,
nameOf(getCurrentCallsLimit),
"GET",
"/management/consumers/CONSUMER_ID/consumer/current-usage",
- "Get Call Limits for a Consumer Usage",
+ "Get Rate Limits for a Consumer Usage",
s"""
- |Get Call Limits for a Consumer Usage.
+ |Get Rate Limits for a Consumer Usage.
|${userAuthenticationMessage(true)}
|
|""".stripMargin,
@@ -191,10 +193,10 @@ trait APIMethods600 {
implementedInApiVersion,
nameOf(createCallLimits),
"POST",
- "/management/consumers/CONSUMER_ID/consumer/call-limits",
- "Create Call Limits for a Consumer",
+ "/management/consumers/CONSUMER_ID/consumer/rate-limits",
+ "Create Rate Limits for a Consumer",
s"""
- |Create Call Limits for a Consumer
+ |Create Rate Limits for a Consumer
|
|${userAuthenticationMessage(true)}
|
@@ -210,21 +212,21 @@ trait APIMethods600 {
UnknownError
),
List(apiTagConsumer),
- Some(List(canSetCallLimits)))
+ Some(List(canCreateRateLimits)))
lazy val createCallLimits: OBPEndpoint = {
- case "management" :: "consumers" :: consumerId :: "consumer" :: "call-limits" :: Nil JsonPost json -> _ =>
+ case "management" :: "consumers" :: consumerId :: "consumer" :: "rate-limits" :: Nil JsonPost json -> _ =>
cc =>
implicit val ec = EndpointContext(Some(cc))
for {
(Full(u), callContext) <- authenticatedAccess(cc)
- _ <- NewStyle.function.hasEntitlement("", u.userId, canSetCallLimits, callContext)
+ _ <- NewStyle.function.hasEntitlement("", u.userId, canCreateRateLimits, callContext)
postJson <- NewStyle.function.tryons(s"$InvalidJsonFormat The Json body should be the $CallLimitPostJsonV600 ", 400, callContext) {
json.extract[CallLimitPostJsonV600]
}
_ <- NewStyle.function.getConsumerByConsumerId(consumerId, callContext)
- rateLimiting <- RateLimitingDI.rateLimiting.vend.createOrUpdateConsumerCallLimits(
+ rateLimiting <- RateLimitingDI.rateLimiting.vend.createConsumerCallLimits(
consumerId,
postJson.from_date,
postJson.to_date,
@@ -247,15 +249,84 @@ trait APIMethods600 {
}
+ staticResourceDocs += ResourceDoc(
+ updateRateLimits,
+ implementedInApiVersion,
+ nameOf(updateRateLimits),
+ "PUT",
+ "/management/consumers/CONSUMER_ID/consumer/rate-limits/RATE_LIMITING_ID",
+ "Set Rate Limits / Call Limits per Consumer",
+ s"""
+ |Set the API rate limits / call limits for a Consumer:
+ |
+ |Rate limiting can be set:
+ |
+ |Per Second
+ |Per Minute
+ |Per Hour
+ |Per Week
+ |Per Month
+ |
+ |
+ |${userAuthenticationMessage(true)}
+ |
+ |""".stripMargin,
+ callLimitPostJsonV400,
+ callLimitPostJsonV400,
+ List(
+ UserNotLoggedIn,
+ InvalidJsonFormat,
+ InvalidConsumerId,
+ ConsumerNotFoundByConsumerId,
+ UserHasMissingRoles,
+ UpdateConsumerError,
+ UnknownError
+ ),
+ List(apiTagConsumer, apiTagRateLimits),
+ Some(List(canUpdateRateLimits)))
+
+ lazy val updateRateLimits: OBPEndpoint = {
+ case "management" :: "consumers" :: consumerId :: "consumer" :: "rate-limits" :: rateLimitingId :: Nil JsonPut json -> _ => {
+ cc =>
+ implicit val ec = EndpointContext(Some(cc))
+ for {
+ (Full(u), callContext) <- authenticatedAccess(cc)
+ _ <- NewStyle.function.handleEntitlementsAndScopes("", u.userId, List(canUpdateRateLimits), callContext)
+ postJson <- NewStyle.function.tryons(s"$InvalidJsonFormat The Json body should be the $CallLimitPostJsonV400 ", 400, callContext) {
+ json.extract[CallLimitPostJsonV400]
+ }
+ _ <- NewStyle.function.getConsumerByConsumerId(consumerId, callContext)
+ rateLimiting <- RateLimitingDI.rateLimiting.vend.updateConsumerCallLimits(
+ rateLimitingId,
+ postJson.from_date,
+ postJson.to_date,
+ postJson.api_version,
+ postJson.api_name,
+ postJson.bank_id,
+ Some(postJson.per_second_call_limit),
+ Some(postJson.per_minute_call_limit),
+ Some(postJson.per_hour_call_limit),
+ Some(postJson.per_day_call_limit),
+ Some(postJson.per_week_call_limit),
+ Some(postJson.per_month_call_limit)) map {
+ unboxFullOrFail(_, callContext, UpdateConsumerError)
+ }
+ } yield {
+ (createCallsLimitJson(rateLimiting), HttpCode.`200`(callContext))
+ }
+ }
+ }
+
+
staticResourceDocs += ResourceDoc(
deleteCallLimits,
implementedInApiVersion,
nameOf(deleteCallLimits),
"DELETE",
- "/management/consumers/CONSUMER_ID/consumer/call-limits/RATE_LIMITING_ID",
- "Delete Call Limit by Rate Limiting ID",
+ "/management/consumers/CONSUMER_ID/consumer/rate-limits/RATE_LIMITING_ID",
+ "Delete Rate Limit by Rate Limiting ID",
s"""
- |Delete a specific Call Limit by Rate Limiting ID
+ |Delete a specific Rate Limit by Rate Limiting ID
|
|${userAuthenticationMessage(true)}
|
@@ -270,16 +341,16 @@ trait APIMethods600 {
UnknownError
),
List(apiTagConsumer),
- Some(List(canDeleteRateLimiting)))
+ Some(List(canDeleteRateLimits)))
lazy val deleteCallLimits: OBPEndpoint = {
- case "management" :: "consumers" :: consumerId :: "consumer" :: "call-limits" :: rateLimitingId :: Nil JsonDelete _ =>
+ case "management" :: "consumers" :: consumerId :: "consumer" :: "rate-limits" :: rateLimitingId :: Nil JsonDelete _ =>
cc =>
implicit val ec = EndpointContext(Some(cc))
for {
(Full(u), callContext) <- authenticatedAccess(cc)
- _ <- NewStyle.function.hasEntitlement("", u.userId, canDeleteRateLimiting, callContext)
+ _ <- NewStyle.function.hasEntitlement("", u.userId, canDeleteRateLimits, callContext)
_ <- NewStyle.function.getConsumerByConsumerId(consumerId, callContext)
rateLimiting <- RateLimitingDI.rateLimiting.vend.getByRateLimitingId(rateLimitingId)
_ <- rateLimiting match {
@@ -305,10 +376,10 @@ trait APIMethods600 {
implementedInApiVersion,
nameOf(getActiveCallLimitsAtDate),
"GET",
- "/management/consumers/CONSUMER_ID/consumer/call-limits/active-at-date/DATE",
- "Get Active Call Limits at Date",
+ "/management/consumers/CONSUMER_ID/consumer/rate-limits/active-at-date/DATE",
+ "Get Active Rate Limits at Date",
s"""
- |Get the sum of call limits at a certain date time. This returns a SUM of all the records that span that time.
+ |Get the sum of rate limits at a certain date time. This returns a SUM of all the records that span that time.
|
|Date format: YYYY-MM-DDTHH:MM:SSZ (e.g. 1099-12-31T23:00:00Z)
|
@@ -330,7 +401,7 @@ trait APIMethods600 {
lazy val getActiveCallLimitsAtDate: OBPEndpoint = {
- case "management" :: "consumers" :: consumerId :: "consumer" :: "call-limits" :: "active-at-date" :: dateString :: Nil JsonGet _ =>
+ case "management" :: "consumers" :: consumerId :: "consumer" :: "rate-limits" :: "active-at-date" :: dateString :: Nil JsonGet _ =>
cc =>
implicit val ec = EndpointContext(Some(cc))
for {
@@ -520,13 +591,14 @@ trait APIMethods600 {
|The user creating this will be automatically assigned the Role CanCreateEntitlementAtOneBank.
|Thus the User can manage the bank they create and assign Roles to other Users.
|
- |Only SANDBOX mode
- |The settlement accounts are created specified by the bank in the POST body.
+ Only SANDBOX mode (i.e. when connector=mapped in properties file)
+ |The settlement accounts are automatically created by the system when the bank is created.
|Name and account id are created in accordance to the next rules:
| - Incoming account (name: Default incoming settlement account, Account ID: OBP_DEFAULT_INCOMING_ACCOUNT_ID, currency: EUR)
| - Outgoing account (name: Default outgoing settlement account, Account ID: OBP_DEFAULT_OUTGOING_ACCOUNT_ID, currency: EUR)
|
|""",
+
postBankJson600,
bankJson500,
List(
@@ -617,7 +689,7 @@ trait APIMethods600 {
|DirectLogin is a simple authentication flow. You POST your credentials (username, password, and consumer key)
|to the DirectLogin endpoint and receive a token in return.
|
- |This is an alias to the legacy DirectLogin endpoint that includes the standard API versioning prefix.
+ |This is an alias to the DirectLogin endpoint that includes the standard API versioning prefix.
|
|This endpoint requires the following headers:
|- DirectLogin: username=YOUR_USERNAME, password=YOUR_PASSWORD, consumer_key=YOUR_CONSUMER_KEY
diff --git a/obp-api/src/main/scala/code/ratelimiting/MappedRateLimiting.scala b/obp-api/src/main/scala/code/ratelimiting/MappedRateLimiting.scala
index 03f46f6182..844e38f5d4 100644
--- a/obp-api/src/main/scala/code/ratelimiting/MappedRateLimiting.scala
+++ b/obp-api/src/main/scala/code/ratelimiting/MappedRateLimiting.scala
@@ -123,6 +123,44 @@ object MappedRateLimitingProvider extends RateLimitingProviderTrait {
).headOption
}
+ def createConsumerCallLimits(consumerId: String,
+ fromDate: Date,
+ toDate: Date,
+ apiVersion: Option[String],
+ apiName: Option[String],
+ bankId: Option[String],
+ perSecond: Option[String],
+ perMinute: Option[String],
+ perHour: Option[String],
+ perDay: Option[String],
+ perWeek: Option[String],
+ perMonth: Option[String]): Future[Box[RateLimiting]] = Future {
+
+ def createRateLimit(c: RateLimiting): Box[RateLimiting] = {
+ tryo {
+ c.FromDate(fromDate)
+ c.ToDate(toDate)
+
+ perSecond.foreach(v => c.PerSecondCallLimit(v.toLong))
+ perMinute.foreach(v => c.PerMinuteCallLimit(v.toLong))
+ perHour.foreach(v => c.PerHourCallLimit(v.toLong))
+ perDay.foreach(v => c.PerDayCallLimit(v.toLong))
+ perWeek.foreach(v => c.PerWeekCallLimit(v.toLong))
+ perMonth.foreach(v => c.PerMonthCallLimit(v.toLong))
+
+ c.BankId(bankId.orNull)
+ c.ApiName(apiName.orNull)
+ c.ApiVersion(apiVersion.orNull)
+ c.ConsumerId(consumerId)
+
+ c.updatedAt(new Date())
+
+ c.saveMe()
+ }
+ }
+ val result = createRateLimit(RateLimiting.create)
+ result
+ }
def createOrUpdateConsumerCallLimits(consumerId: String,
fromDate: Date,
toDate: Date,
@@ -153,7 +191,6 @@ object MappedRateLimitingProvider extends RateLimitingProviderTrait {
c.ApiVersion(apiVersion.orNull)
c.ConsumerId(consumerId)
- // 👇 bump timestamp for last-write-wins
c.updatedAt(new Date())
c.saveMe()
@@ -167,6 +204,40 @@ object MappedRateLimitingProvider extends RateLimitingProviderTrait {
result
}
+ def updateConsumerCallLimits(rateLimitingId: String,
+ fromDate: Date,
+ toDate: Date,
+ apiVersion: Option[String],
+ apiName: Option[String],
+ bankId: Option[String],
+ perSecond: Option[String],
+ perMinute: Option[String],
+ perHour: Option[String],
+ perDay: Option[String],
+ perWeek: Option[String],
+ perMonth: Option[String]): Future[Box[RateLimiting]] = Future {
+ RateLimiting.find(
+ By(RateLimiting.RateLimitingId, rateLimitingId)
+ ) map { c =>
+ c.FromDate(fromDate)
+ c.ToDate(toDate)
+
+ perSecond.foreach(v => c.PerSecondCallLimit(v.toLong))
+ perMinute.foreach(v => c.PerMinuteCallLimit(v.toLong))
+ perHour.foreach(v => c.PerHourCallLimit(v.toLong))
+ perDay.foreach(v => c.PerDayCallLimit(v.toLong))
+ perWeek.foreach(v => c.PerWeekCallLimit(v.toLong))
+ perMonth.foreach(v => c.PerMonthCallLimit(v.toLong))
+
+ c.BankId(bankId.orNull)
+ c.ApiName(apiName.orNull)
+ c.ApiVersion(apiVersion.orNull)
+
+ c.updatedAt(new Date())
+
+ c.saveMe()
+ }
+ }
def deleteByRateLimitingId(rateLimitingId: String): Future[Box[Boolean]] = Future {
tryo {
diff --git a/obp-api/src/main/scala/code/ratelimiting/RateLimiting.scala b/obp-api/src/main/scala/code/ratelimiting/RateLimiting.scala
index 5dfbf0ba27..f27b106ea6 100644
--- a/obp-api/src/main/scala/code/ratelimiting/RateLimiting.scala
+++ b/obp-api/src/main/scala/code/ratelimiting/RateLimiting.scala
@@ -30,6 +30,30 @@ trait RateLimitingProviderTrait {
perDay: Option[String],
perWeek: Option[String],
perMonth: Option[String]): Future[Box[RateLimiting]]
+ def updateConsumerCallLimits(rateLimitingId: String,
+ fromDate: Date,
+ toDate: Date,
+ apiVersion: Option[String],
+ apiName: Option[String],
+ bankId: Option[String],
+ perSecond: Option[String],
+ perMinute: Option[String],
+ perHour: Option[String],
+ perDay: Option[String],
+ perWeek: Option[String],
+ perMonth: Option[String]): Future[Box[RateLimiting]]
+ def createConsumerCallLimits(consumerId: String,
+ fromDate: Date,
+ toDate: Date,
+ apiVersion: Option[String],
+ apiName: Option[String],
+ bankId: Option[String],
+ perSecond: Option[String],
+ perMinute: Option[String],
+ perHour: Option[String],
+ perDay: Option[String],
+ perWeek: Option[String],
+ perMonth: Option[String]): Future[Box[RateLimiting]]
def deleteByRateLimitingId(rateLimitingId: String): Future[Box[Boolean]]
def getByRateLimitingId(rateLimitingId: String): Future[Box[RateLimiting]]
def getActiveCallLimitsByConsumerIdAtDate(consumerId: String, date: Date): Future[List[RateLimiting]]
diff --git a/obp-api/src/main/scala/code/util/SecureLogging.scala b/obp-api/src/main/scala/code/util/SecureLogging.scala
index 98ec9bfe0f..1c3b28b0f4 100644
--- a/obp-api/src/main/scala/code/util/SecureLogging.scala
+++ b/obp-api/src/main/scala/code/util/SecureLogging.scala
@@ -37,6 +37,9 @@ object SecureLogging {
conditionalPattern("securelogging_mask_client_secret") {
(Pattern.compile("(?i)(client_secret[\"']?\\s*[:=]\\s*[\"']?)([^\"',\\s&]+)"), "$1***")
},
+ conditionalPattern("securelogging_mask_client_secret") {
+ (Pattern.compile("(?i)(client_secret\\s*->\\s*)([^,\\s&\\)]+)"), "$1***")
+ },
// Authorization / Tokens
conditionalPattern("securelogging_mask_authorization") {
@@ -45,31 +48,55 @@ object SecureLogging {
conditionalPattern("securelogging_mask_access_token") {
(Pattern.compile("(?i)(access_token[\"']?\\s*[:=]\\s*[\"']?)([^\"',\\s&]+)"), "$1***")
},
+ conditionalPattern("securelogging_mask_access_token") {
+ (Pattern.compile("(?i)(access_token\\s*->\\s*)([^,\\s&\\)]+)"), "$1***")
+ },
conditionalPattern("securelogging_mask_refresh_token") {
(Pattern.compile("(?i)(refresh_token[\"']?\\s*[:=]\\s*[\"']?)([^\"',\\s&]+)"), "$1***")
},
+ conditionalPattern("securelogging_mask_refresh_token") {
+ (Pattern.compile("(?i)(refresh_token\\s*->\\s*)([^,\\s&\\)]+)"), "$1***")
+ },
conditionalPattern("securelogging_mask_id_token") {
(Pattern.compile("(?i)(id_token[\"']?\\s*[:=]\\s*[\"']?)([^\"',\\s&]+)"), "$1***")
},
+ conditionalPattern("securelogging_mask_id_token") {
+ (Pattern.compile("(?i)(id_token\\s*->\\s*)([^,\\s&\\)]+)"), "$1***")
+ },
conditionalPattern("securelogging_mask_token") {
(Pattern.compile("(?i)(token[\"']?\\s*[:=]\\s*[\"']?)([^\"',\\s&]+)"), "$1***")
},
+ conditionalPattern("securelogging_mask_token") {
+ (Pattern.compile("(?i)(token\\s*->\\s*)([^,\\s&\\)]+)"), "$1***")
+ },
// Passwords
conditionalPattern("securelogging_mask_password") {
(Pattern.compile("(?i)(password[\"']?\\s*[:=]\\s*[\"']?)([^\"',\\s&]+)"), "$1***")
},
+ conditionalPattern("securelogging_mask_password") {
+ (Pattern.compile("(?i)(password\\s*->\\s*)([^,\\s&\\)]+)"), "$1***")
+ },
// API keys
conditionalPattern("securelogging_mask_api_key") {
(Pattern.compile("(?i)(api_key[\"']?\\s*[:=]\\s*[\"']?)([^\"',\\s&]+)"), "$1***")
},
+ conditionalPattern("securelogging_mask_api_key") {
+ (Pattern.compile("(?i)(api_key\\s*->\\s*)([^,\\s&\\)]+)"), "$1***")
+ },
conditionalPattern("securelogging_mask_key") {
(Pattern.compile("(?i)(key[\"']?\\s*[:=]\\s*[\"']?)([^\"',\\s&]+)"), "$1***")
},
+ conditionalPattern("securelogging_mask_key") {
+ (Pattern.compile("(?i)(key\\s*->\\s*)([^,\\s&\\)]+)"), "$1***")
+ },
conditionalPattern("securelogging_mask_private_key") {
(Pattern.compile("(?i)(private_key[\"']?\\s*[:=]\\s*[\"']?)([^\"',\\s&]+)"), "$1***")
},
+ conditionalPattern("securelogging_mask_private_key") {
+ (Pattern.compile("(?i)(private_key\\s*->\\s*)([^,\\s&\\)]+)"), "$1***")
+ },
// Database
conditionalPattern("securelogging_mask_jdbc") {
@@ -158,7 +185,14 @@ object SecureLogging {
"api_key=sk_test_1234567890abcdef",
"Error connecting to jdbc:mysql://localhost:3306/obp?user=admin:secretpassword@dbhost",
"Credit card: 4532-1234-5678-9012 was processed",
- "User email: sensitive@example.com in auth context"
+ "User email: sensitive@example.com in auth context",
+ "Map(client_secret -> my_client_secret, token -> secret_token)",
+ "Map(client_secret->my_client_secret, access_token->oauth_token_123)",
+ "directLoginParams=Map(password -> secret123, api_key -> sk_live_key)",
+ "client_secret -> my_client_secret",
+ "client_secret->my_client_secret",
+ "CallContext(oAuthParams=Map(access_token -> bearer_token, client_secret->sensitive_key))",
+ "Map(token->private_token, password -> supersecret, api_key->sk_live_123)"
)
testMessages.map(msg => (msg, maskSensitive(msg)))
}
diff --git a/obp-api/src/test/scala/code/api/v3_1_0/RateLimitTest.scala b/obp-api/src/test/scala/code/api/v3_1_0/RateLimitTest.scala
index 612d95f866..6aeca45e0e 100644
--- a/obp-api/src/test/scala/code/api/v3_1_0/RateLimitTest.scala
+++ b/obp-api/src/test/scala/code/api/v3_1_0/RateLimitTest.scala
@@ -32,7 +32,7 @@ import java.time.{ZoneId, ZonedDateTime}
import java.util.Date
import code.api.util.APIUtil.OAuth._
import code.api.util.{ApiRole, RateLimitingUtil}
-import code.api.util.ApiRole.{CanReadCallLimits, CanSetCallLimits}
+import code.api.util.ApiRole.{CanReadCallLimits, CanUpdateRateLimits}
import code.api.util.ErrorMessages.{UserHasMissingRoles, UserNotLoggedIn}
import code.api.v3_1_0.OBPAPI3_1_0.Implementations3_1_0
import code.consumer.Consumers
@@ -155,22 +155,22 @@ class RateLimitTest extends V310ServerSetup with PropsReset {
And("error should be " + UserNotLoggedIn)
response310.body.extract[ErrorMessage].message should equal (UserNotLoggedIn)
}
- scenario("We will try to set calls limit per minute without a proper Role " + ApiRole.canSetCallLimits, ApiEndpoint, VersionOfApi) {
- When("We make a request v3.1.0 without a Role " + ApiRole.canSetCallLimits)
+ scenario("We will try to set calls limit per minute without a proper Role " + ApiRole.canUpdateRateLimits, ApiEndpoint, VersionOfApi) {
+ When("We make a request v3.1.0 without a Role " + ApiRole.canUpdateRateLimits)
val Some((c, _)) = user1
val consumerId = Consumers.consumers.vend.getConsumerByConsumerKey(c.key).map(_.consumerId.get).getOrElse("")
val request310 = (v3_1_0_Request / "management" / "consumers" / consumerId / "consumer" / "call-limits").PUT <@(user1)
val response310 = makePutRequest(request310, write(callLimitJson1))
Then("We should get a 403")
response310.code should equal(403)
- And("error should be " + UserHasMissingRoles + CanSetCallLimits)
- response310.body.extract[ErrorMessage].message should equal (UserHasMissingRoles + CanSetCallLimits)
+ And("error should be " + UserHasMissingRoles + CanUpdateRateLimits)
+ response310.body.extract[ErrorMessage].message should equal (UserHasMissingRoles + CanUpdateRateLimits)
}
- scenario("We will try to set calls limit per minute with a proper Role " + ApiRole.canSetCallLimits, ApiEndpoint, VersionOfApi) {
- When("We make a request v3.1.0 with a Role " + ApiRole.canSetCallLimits)
+ scenario("We will try to set calls limit per minute with a proper Role " + ApiRole.canUpdateRateLimits, ApiEndpoint, VersionOfApi) {
+ When("We make a request v3.1.0 with a Role " + ApiRole.canUpdateRateLimits)
val Some((c, _)) = user1
val consumerId = Consumers.consumers.vend.getConsumerByConsumerKey(c.key).map(_.consumerId.get).getOrElse("")
- Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, ApiRole.CanSetCallLimits.toString)
+ Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, ApiRole.CanUpdateRateLimits.toString)
val request310 = (v3_1_0_Request / "management" / "consumers" / consumerId / "consumer" / "call-limits").PUT <@(user1)
val response310 = makePutRequest(request310, write(callLimitJson1))
Then("We should get a 200")
@@ -179,11 +179,11 @@ class RateLimitTest extends V310ServerSetup with PropsReset {
}
scenario("We will set calls limit per second for a Consumer", ApiEndpoint, VersionOfApi) {
- When("We make a request v3.1.0 with a Role " + ApiRole.canSetCallLimits)
+ When("We make a request v3.1.0 with a Role " + ApiRole.canUpdateRateLimits)
val Some((c, _)) = user1
val consumerId = Consumers.consumers.vend.getConsumerByConsumerKey(c.key).map(_.consumerId.get).getOrElse("")
val id: Long = Consumers.consumers.vend.getConsumerByConsumerKey(c.key).map(_.id.get).getOrElse(0)
- Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, ApiRole.CanSetCallLimits.toString)
+ Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, ApiRole.CanUpdateRateLimits.toString)
val request310 = (v3_1_0_Request / "management" / "consumers" / consumerId / "consumer" / "call-limits").PUT <@(user1)
val response01 = makePutRequest(request310, write(callLimitSecondJson))
Then("We should get a 200")
@@ -204,11 +204,11 @@ class RateLimitTest extends V310ServerSetup with PropsReset {
}
scenario("We will set calls limit per minute for a Consumer", ApiEndpoint, VersionOfApi) {
- When("We make a request v3.1.0 with a Role " + ApiRole.canSetCallLimits)
+ When("We make a request v3.1.0 with a Role " + ApiRole.canUpdateRateLimits)
val Some((c, _)) = user1
val consumerId = Consumers.consumers.vend.getConsumerByConsumerKey(c.key).map(_.consumerId.get).getOrElse("")
val id: Long = Consumers.consumers.vend.getConsumerByConsumerKey(c.key).map(_.id.get).getOrElse(0)
- Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, ApiRole.CanSetCallLimits.toString)
+ Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, ApiRole.CanUpdateRateLimits.toString)
val request310 = (v3_1_0_Request / "management" / "consumers" / consumerId / "consumer" / "call-limits").PUT <@(user1)
val response01 = makePutRequest(request310, write(callLimitMinuteJson))
Then("We should get a 200")
@@ -229,11 +229,11 @@ class RateLimitTest extends V310ServerSetup with PropsReset {
}
scenario("We will set calls limit per hour for a Consumer", ApiEndpoint, VersionOfApi) {
- When("We make a request v3.1.0 with a Role " + ApiRole.canSetCallLimits)
+ When("We make a request v3.1.0 with a Role " + ApiRole.canUpdateRateLimits)
val Some((c, _)) = user1
val consumerId = Consumers.consumers.vend.getConsumerByConsumerKey(c.key).map(_.consumerId.get).getOrElse("")
val id: Long = Consumers.consumers.vend.getConsumerByConsumerKey(c.key).map(_.id.get).getOrElse(0)
- Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, ApiRole.CanSetCallLimits.toString)
+ Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, ApiRole.CanUpdateRateLimits.toString)
val request310 = (v3_1_0_Request / "management" / "consumers" / consumerId / "consumer" / "call-limits").PUT <@(user1)
val response01 = makePutRequest(request310, write(callLimitHourJson))
Then("We should get a 200")
@@ -254,11 +254,11 @@ class RateLimitTest extends V310ServerSetup with PropsReset {
}
scenario("We will set calls limit per day for a Consumer", ApiEndpoint, VersionOfApi) {
- When("We make a request v3.1.0 with a Role " + ApiRole.canSetCallLimits)
+ When("We make a request v3.1.0 with a Role " + ApiRole.canUpdateRateLimits)
val Some((c, _)) = user1
val consumerId = Consumers.consumers.vend.getConsumerByConsumerKey(c.key).map(_.consumerId.get).getOrElse("")
val id: Long = Consumers.consumers.vend.getConsumerByConsumerKey(c.key).map(_.id.get).getOrElse(0)
- Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, ApiRole.CanSetCallLimits.toString)
+ Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, ApiRole.CanUpdateRateLimits.toString)
val request310 = (v3_1_0_Request / "management" / "consumers" / consumerId / "consumer" / "call-limits").PUT <@(user1)
val response01 = makePutRequest(request310, write(callLimitDayJson))
Then("We should get a 200")
@@ -279,11 +279,11 @@ class RateLimitTest extends V310ServerSetup with PropsReset {
}
scenario("We will set calls limit per week for a Consumer", ApiEndpoint, VersionOfApi) {
- When("We make a request v3.1.0 with a Role " + ApiRole.canSetCallLimits)
+ When("We make a request v3.1.0 with a Role " + ApiRole.canUpdateRateLimits)
val Some((c, _)) = user1
val consumerId = Consumers.consumers.vend.getConsumerByConsumerKey(c.key).map(_.consumerId.get).getOrElse("")
val id: Long = Consumers.consumers.vend.getConsumerByConsumerKey(c.key).map(_.id.get).getOrElse(0)
- Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, ApiRole.CanSetCallLimits.toString)
+ Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, ApiRole.CanUpdateRateLimits.toString)
val request310 = (v3_1_0_Request / "management" / "consumers" / consumerId / "consumer" / "call-limits").PUT <@(user1)
val response01 = makePutRequest(request310, write(callLimitWeekJson))
Then("We should get a 200")
@@ -304,11 +304,11 @@ class RateLimitTest extends V310ServerSetup with PropsReset {
}
scenario("We will set calls limit per month for a Consumer", ApiEndpoint, VersionOfApi) {
- When("We make a request v3.1.0 with a Role " + ApiRole.canSetCallLimits)
+ When("We make a request v3.1.0 with a Role " + ApiRole.canUpdateRateLimits)
val Some((c, _)) = user1
val consumerId = Consumers.consumers.vend.getConsumerByConsumerKey(c.key).map(_.consumerId.get).getOrElse("")
val id: Long = Consumers.consumers.vend.getConsumerByConsumerKey(c.key).map(_.id.get).getOrElse(0)
- Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, ApiRole.CanSetCallLimits.toString)
+ Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, ApiRole.CanUpdateRateLimits.toString)
val request310 = (v3_1_0_Request / "management" / "consumers" / consumerId / "consumer" / "call-limits").PUT <@(user1)
val response01 = makePutRequest(request310, write(callLimitMonthJson))
Then("We should get a 200")
diff --git a/obp-api/src/test/scala/code/api/v4_0_0/RateLimitingTest.scala b/obp-api/src/test/scala/code/api/v4_0_0/RateLimitingTest.scala
index 36a93050c6..d0a76181c5 100644
--- a/obp-api/src/test/scala/code/api/v4_0_0/RateLimitingTest.scala
+++ b/obp-api/src/test/scala/code/api/v4_0_0/RateLimitingTest.scala
@@ -27,7 +27,7 @@ package code.api.v4_0_0
import code.api.cache.Redis
import code.api.util.APIUtil.OAuth._
-import code.api.util.ApiRole.{CanSetCallLimits, canCreateDynamicEndpoint}
+import code.api.util.ApiRole.{CanUpdateRateLimits, canCreateDynamicEndpoint}
import code.api.util.ErrorMessages.{UserHasMissingRoles, UserNotLoggedIn}
import code.api.util.{ApiRole, ExampleValue, RateLimitingUtil}
import code.api.v3_0_0.OBPAPI3_0_0.Implementations3_0_0.getCurrentUser
@@ -101,18 +101,18 @@ class RateLimitingTest extends V400ServerSetup with PropsReset {
And("error should be " + UserNotLoggedIn)
response400.body.extract[ErrorMessage].message should equal (UserNotLoggedIn)
}
- scenario("We will try to set Rate Limiting per minute without a proper Role " + ApiRole.canSetCallLimits, ApiCallsLimit, ApiVersion400) {
+ scenario("We will try to set Rate Limiting per minute without a proper Role " + ApiRole.canUpdateRateLimits, ApiCallsLimit, ApiVersion400) {
- When("We make a request v4.0.0 without a Role " + ApiRole.canSetCallLimits)
+ When("We make a request v4.0.0 without a Role " + ApiRole.canUpdateRateLimits)
val response400 = setRateLimitingWithoutRole(user1, callLimitJsonInitial)
Then("We should get a 403")
response400.code should equal(403)
- And("error should be " + UserHasMissingRoles + CanSetCallLimits)
- response400.body.extract[ErrorMessage].message should equal (UserHasMissingRoles + CanSetCallLimits)
+ And("error should be " + UserHasMissingRoles + CanUpdateRateLimits)
+ response400.body.extract[ErrorMessage].message should equal (UserHasMissingRoles + CanUpdateRateLimits)
}
- scenario("We will try to set Rate Limiting per minute with a proper Role " + ApiRole.canSetCallLimits, ApiCallsLimit, ApiVersion400) {
+ scenario("We will try to set Rate Limiting per minute with a proper Role " + ApiRole.canUpdateRateLimits, ApiCallsLimit, ApiVersion400) {
- When("We make a request v4.0.0 with a Role " + ApiRole.canSetCallLimits)
+ When("We make a request v4.0.0 with a Role " + ApiRole.canUpdateRateLimits)
val response400 = setRateLimiting(user1, callLimitJsonInitial)
Then("We should get a 200")
response400.code should equal(200)
@@ -120,7 +120,7 @@ class RateLimitingTest extends V400ServerSetup with PropsReset {
}
scenario("We will set Rate Limiting per second for an Endpoint", ApiCallsLimit, ApiVersion400) {
- When("We make a request v4.0.0 with a Role " + ApiRole.canSetCallLimits)
+ When("We make a request v4.0.0 with a Role " + ApiRole.canUpdateRateLimits)
val response01 = setRateLimiting(user1, callLimitJsonSecond)
Then("We should get a 200")
response01.code should equal(200)
@@ -137,13 +137,13 @@ class RateLimitingTest extends V400ServerSetup with PropsReset {
response03.code should equal(429)
// Revert to initial state
- val response04 = setRateLimiting(user1, callLimitJsonInitial)
+ val response04 = setRateLimiting2(user1, callLimitJsonInitial)
Then("We should get a 200")
response04.code should equal(200)
}
scenario("We will set Rate Limiting per minute for an Endpoint", ApiCallsLimit, ApiVersion400) {
- When("We make a request v4.0.0 with a Role " + ApiRole.canSetCallLimits)
+ When("We make a request v4.0.0 with a Role " + ApiRole.canUpdateRateLimits)
val response01 = setRateLimiting(user1, callLimitJsonMinute)
Then("We should get a 200")
response01.code should equal(200)
@@ -159,13 +159,13 @@ class RateLimitingTest extends V400ServerSetup with PropsReset {
response03.code should equal(429)
// Revert to initial state
- val response04 = setRateLimiting(user1, callLimitJsonInitial)
+ val response04 = setRateLimiting2(user1, callLimitJsonInitial)
Then("We should get a 200")
response04.code should equal(200)
}
scenario("We will set Rate Limiting per hour for an Endpoint", ApiCallsLimit, ApiVersion400) {
- When("We make a request v4.0.0 with a Role " + ApiRole.canSetCallLimits)
+ When("We make a request v4.0.0 with a Role " + ApiRole.canUpdateRateLimits)
val response01 = setRateLimiting(user1, callLimitJsonHour)
Then("We should get a 200")
response01.code should equal(200)
@@ -181,13 +181,13 @@ class RateLimitingTest extends V400ServerSetup with PropsReset {
response03.code should equal(429)
// Revert to initial state
- val response04 = setRateLimiting(user1, callLimitJsonInitial)
+ val response04 = setRateLimiting2(user1, callLimitJsonInitial)
Then("We should get a 200")
response04.code should equal(200)
}
scenario("We will set Rate Limiting per week for an Endpoint", ApiCallsLimit, ApiVersion400) {
- When("We make a request v4.0.0 with a Role " + ApiRole.canSetCallLimits)
+ When("We make a request v4.0.0 with a Role " + ApiRole.canUpdateRateLimits)
val response01 = setRateLimiting(user1, callLimitJsonWeek)
Then("We should get a 200")
response01.code should equal(200)
@@ -203,13 +203,13 @@ class RateLimitingTest extends V400ServerSetup with PropsReset {
response03.code should equal(429)
// Revert to initial state
- val response04 = setRateLimiting(user1, callLimitJsonInitial)
+ val response04 = setRateLimiting2(user1, callLimitJsonInitial)
Then("We should get a 200")
response04.code should equal(200)
}
scenario("We will set Rate Limiting per month for an Endpoint", ApiCallsLimit, ApiVersion400) {
- When("We make a request v4.0.0 with a Role " + ApiRole.canSetCallLimits)
+ When("We make a request v4.0.0 with a Role " + ApiRole.canUpdateRateLimits)
val response01 = setRateLimiting(user1, callLimitJsonMonth)
Then("We should get a 200")
response01.code should equal(200)
@@ -225,7 +225,7 @@ class RateLimitingTest extends V400ServerSetup with PropsReset {
response03.code should equal(429)
// Revert to initial state
- val response04 = setRateLimiting(user1, callLimitJsonInitial)
+ val response04 = setRateLimiting2(user1, callLimitJsonInitial)
Then("We should get a 200")
response04.code should equal(200)
}
@@ -248,7 +248,7 @@ class RateLimitingTest extends V400ServerSetup with PropsReset {
val operationId = "dynamicEndpoint_GET_accounts_ACCOUNT_ID"
val apiName = "dynamicEndpoint_GET_accounts_ACCOUNT_ID"
val apiVersion = ApiVersion.`dynamic-endpoint`.toString()
- val response01 = setRateLimiting(user1, callLimitJsonHour.copy(api_name = Some(apiName), api_version = Some(apiVersion)))
+ val response01 = setRateLimiting2(user1, callLimitJsonHour.copy(api_name = Some(apiName), api_version = Some(apiVersion)))
Then("We should get a 200")
response01.code should equal(200)
@@ -263,7 +263,7 @@ class RateLimitingTest extends V400ServerSetup with PropsReset {
makeGetRequest(requestDynamicEndpoint.GET <@(user1)).code should equal(429)
// Revert Rate Limiting to initial state in case of a Dynamic Endpoint
- val response02 = setRateLimiting(user1, callLimitJsonInitial.copy(api_name = Some(apiName), api_version = Some(apiVersion)))
+ val response02 = setRateLimiting2(user1, callLimitJsonInitial.copy(api_name = Some(apiName), api_version = Some(apiVersion)))
Then("We should get a 200")
response02.code should equal(200)
diff --git a/obp-api/src/test/scala/code/api/v4_0_0/V400ServerSetup.scala b/obp-api/src/test/scala/code/api/v4_0_0/V400ServerSetup.scala
index 86d5ec1117..dbd09abf61 100644
--- a/obp-api/src/test/scala/code/api/v4_0_0/V400ServerSetup.scala
+++ b/obp-api/src/test/scala/code/api/v4_0_0/V400ServerSetup.scala
@@ -104,10 +104,17 @@ trait V400ServerSetup extends ServerSetupWithTestData with DefaultUsers {
def setRateLimiting(consumerAndToken: Option[(Consumer, Token)], putJson: CallLimitPostJsonV400): APIResponse = {
val Some((c, _)) = consumerAndToken
val consumerId = Consumers.consumers.vend.getConsumerByConsumerKey(c.key).map(_.consumerId.get).getOrElse("")
- Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, ApiRole.CanSetCallLimits.toString)
+ Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, ApiRole.CanUpdateRateLimits.toString)
val request400 = (v4_0_0_Request / "management" / "consumers" / consumerId / "consumer" / "call-limits").PUT <@(consumerAndToken)
makePutRequest(request400, write(putJson))
- }
+ }
+ def setRateLimiting2(consumerAndToken: Option[(Consumer, Token)], putJson: CallLimitPostJsonV400): APIResponse = {
+ val Some((c, _)) = consumerAndToken
+ val consumerId = Consumers.consumers.vend.getConsumerByConsumerKey(c.key).map(_.consumerId.get).getOrElse("")
+ Entitlement.entitlement.vend.addEntitlement("", resourceUser2.userId, ApiRole.CanUpdateRateLimits.toString)
+ val request400 = (v4_0_0_Request / "management" / "consumers" / consumerId / "consumer" / "call-limits").PUT <@ user2
+ makePutRequest(request400, write(putJson))
+ }
def setRateLimitingWithoutRole(consumerAndToken: Option[(Consumer, Token)], putJson: CallLimitPostJsonV400): APIResponse = {
val Some((c, _)) = consumerAndToken
val consumerId = Consumers.consumers.vend.getConsumerByConsumerKey(c.key).map(_.consumerId.get).getOrElse("")
diff --git a/obp-api/src/test/scala/code/api/v5_1_0/RateLimitingTest.scala b/obp-api/src/test/scala/code/api/v5_1_0/RateLimitingTest.scala
index 9991aeba54..bda8c01781 100644
--- a/obp-api/src/test/scala/code/api/v5_1_0/RateLimitingTest.scala
+++ b/obp-api/src/test/scala/code/api/v5_1_0/RateLimitingTest.scala
@@ -91,7 +91,7 @@ class RateLimitingTest extends V510ServerSetup with PropsReset {
When(s"We make a request $ApiVersion510")
val Some((c, _)) = user1
val consumerId = Consumers.consumers.vend.getConsumerByConsumerKey(c.key).map(_.consumerId.get).getOrElse("")
- val request510 = (v5_1_0_Request / "management" / "consumers" / consumerId / "consumer" / "call-limits").GET
+ val request510 = (v5_1_0_Request / "management" / "consumers" / consumerId / "consumer" / "rate-limits").GET
val response510 = makeGetRequest(request510)
Then("We should get a 401")
response510.code should equal(401)
@@ -102,7 +102,7 @@ class RateLimitingTest extends V510ServerSetup with PropsReset {
When("We make a request v3.1.0 without a Role " + ApiRole.canReadCallLimits)
val Some((c, _)) = user1
val consumerId = Consumers.consumers.vend.getConsumerByConsumerKey(c.key).map(_.consumerId.get).getOrElse("")
- val request510 = (v5_1_0_Request / "management" / "consumers" / consumerId / "consumer" / "call-limits").GET <@ (user1)
+ val request510 = (v5_1_0_Request / "management" / "consumers" / consumerId / "consumer" / "rate-limits").GET <@ (user1)
val response510 = makeGetRequest(request510)
Then("We should get a 403")
response510.code should equal(403)
@@ -111,7 +111,7 @@ class RateLimitingTest extends V510ServerSetup with PropsReset {
}
scenario("We will try to get calls limit per minute with a proper Role " + ApiRole.canReadCallLimits, ApiCallsLimit, ApiVersion510) {
- When("We make a request v5.1.0 with a Role " + ApiRole.canSetCallLimits)
+ When("We make a request v5.1.0 with a Role " + ApiRole.canUpdateRateLimits)
val response01 = setRateLimiting(user1, callLimitJsonMonth)
Then("We should get a 200")
response01.code should equal(200)
@@ -120,7 +120,7 @@ class RateLimitingTest extends V510ServerSetup with PropsReset {
val Some((c, _)) = user1
val consumerId = Consumers.consumers.vend.getConsumerByConsumerKey(c.key).map(_.consumerId.get).getOrElse("")
Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, ApiRole.CanReadCallLimits.toString)
- val request510 = (v5_1_0_Request / "management" / "consumers" / consumerId / "consumer" / "call-limits").GET <@ (user1)
+ val request510 = (v5_1_0_Request / "management" / "consumers" / consumerId / "consumer" / "rate-limits").GET <@ (user1)
val response510 = makeGetRequest(request510)
Then("We should get a 200")
response510.code should equal(200)
diff --git a/obp-api/src/test/scala/code/api/v5_1_0/V510ServerSetup.scala b/obp-api/src/test/scala/code/api/v5_1_0/V510ServerSetup.scala
index 32fa520658..cbea88008e 100644
--- a/obp-api/src/test/scala/code/api/v5_1_0/V510ServerSetup.scala
+++ b/obp-api/src/test/scala/code/api/v5_1_0/V510ServerSetup.scala
@@ -37,7 +37,7 @@ trait V510ServerSetup extends ServerSetupWithTestData with DefaultUsers {
def setRateLimiting(consumerAndToken: Option[(Consumer, Token)], putJson: CallLimitPostJsonV400): APIResponse = {
val Some((c, _)) = consumerAndToken
val consumerId = Consumers.consumers.vend.getConsumerByConsumerKey(c.key).map(_.consumerId.get).getOrElse("")
- Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, ApiRole.CanSetCallLimits.toString)
+ Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, ApiRole.CanUpdateRateLimits.toString)
val request400 = (v4_0_0_Request / "management" / "consumers" / consumerId / "consumer" / "call-limits").PUT <@ (consumerAndToken)
makePutRequest(request400, write(putJson))
}
diff --git a/obp-api/src/test/scala/code/api/v6_0_0/CallLimitsTest.scala b/obp-api/src/test/scala/code/api/v6_0_0/CallLimitsTest.scala
index 915d4b2b9d..f8869e8817 100644
--- a/obp-api/src/test/scala/code/api/v6_0_0/CallLimitsTest.scala
+++ b/obp-api/src/test/scala/code/api/v6_0_0/CallLimitsTest.scala
@@ -26,7 +26,7 @@ TESOBE (http://www.tesobe.com/)
package code.api.v6_0_0
import code.api.util.APIUtil.OAuth._
-import code.api.util.ApiRole.{CanDeleteRateLimiting, CanReadCallLimits, CanSetCallLimits}
+import code.api.util.ApiRole.{CanDeleteRateLimiting, CanReadCallLimits, CanCreateRateLimits}
import code.api.util.ErrorMessages.{UserHasMissingRoles, UserNotLoggedIn}
import code.api.v6_0_0.OBPAPI6_0_0.Implementations6_0_0
import code.consumer.Consumers
@@ -46,6 +46,7 @@ class CallLimitsTest extends V600ServerSetup {
object VersionOfApi extends Tag(ApiVersion.v6_0_0.toString)
object ApiEndpoint1 extends Tag(nameOf(Implementations6_0_0.createCallLimits))
object ApiEndpoint2 extends Tag(nameOf(Implementations6_0_0.deleteCallLimits))
+ object UpdateRateLimits extends Tag(nameOf(Implementations6_0_0.updateRateLimits))
object ApiEndpoint3 extends Tag(nameOf(Implementations6_0_0.getActiveCallLimitsAtDate))
lazy val postCallLimitJsonV600 = CallLimitPostJsonV600(
@@ -75,7 +76,7 @@ class CallLimitsTest extends V600ServerSetup {
When("We make a request v6.0.0 without user credentials")
val Some((c, _)) = user1
val consumerId = Consumers.consumers.vend.getConsumerByConsumerKey(c.key).map(_.consumerId.get).getOrElse("")
- val request600 = (v6_0_0_Request / "management" / "consumers" / consumerId / "consumer" / "call-limits").POST
+ val request600 = (v6_0_0_Request / "management" / "consumers" / consumerId / "consumer" / "rate-limits").POST
val response600 = makePostRequest(request600, write(postCallLimitJsonV600))
Then("We should get a 401")
response600.code should equal(401)
@@ -89,20 +90,20 @@ class CallLimitsTest extends V600ServerSetup {
When("We make a request v6.0.0 without a proper role")
val Some((c, _)) = user1
val consumerId = Consumers.consumers.vend.getConsumerByConsumerKey(c.key).map(_.consumerId.get).getOrElse("")
- val request600 = (v6_0_0_Request / "management" / "consumers" / consumerId / "consumer" / "call-limits").POST <@ (user1)
+ val request600 = (v6_0_0_Request / "management" / "consumers" / consumerId / "consumer" / "rate-limits").POST <@ (user1)
val response600 = makePostRequest(request600, write(postCallLimitJsonV600))
Then("We should get a 403")
response600.code should equal(403)
- And("error should be " + UserHasMissingRoles + CanSetCallLimits)
- response600.body.extract[ErrorMessage].message should equal(UserHasMissingRoles + CanSetCallLimits)
+ And("error should be " + UserHasMissingRoles + CanCreateRateLimits)
+ response600.body.extract[ErrorMessage].message should equal(UserHasMissingRoles + CanCreateRateLimits)
}
scenario("We will call the endpoint with proper Role", ApiEndpoint1, VersionOfApi) {
When("We make a request v6.0.0 with a proper role")
val Some((c, _)) = user1
val consumerId = Consumers.consumers.vend.getConsumerByConsumerKey(c.key).map(_.consumerId.get).getOrElse("")
- Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, CanSetCallLimits.toString)
- val request600 = (v6_0_0_Request / "management" / "consumers" / consumerId / "consumer" / "call-limits").POST <@ (user1)
+ Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, CanCreateRateLimits.toString)
+ val request600 = (v6_0_0_Request / "management" / "consumers" / consumerId / "consumer" / "rate-limits").POST <@ (user1)
val response600 = makePostRequest(request600, write(postCallLimitJsonV600))
Then("We should get a 201")
response600.code should equal(201)
@@ -119,15 +120,15 @@ class CallLimitsTest extends V600ServerSetup {
Given("We create a call limit first")
val Some((c, _)) = user1
val consumerId = Consumers.consumers.vend.getConsumerByConsumerKey(c.key).map(_.consumerId.get).getOrElse("")
- Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, CanSetCallLimits.toString)
- val request600 = (v6_0_0_Request / "management" / "consumers" / consumerId / "consumer" / "call-limits").POST <@ (user1)
+ Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, CanCreateRateLimits.toString)
+ val request600 = (v6_0_0_Request / "management" / "consumers" / consumerId / "consumer" / "rate-limits").POST <@ (user1)
val createResponse = makePostRequest(request600, write(postCallLimitJsonV600))
createResponse.code should equal(201)
val createdCallLimit = createResponse.body.extract[CallLimitJsonV600]
When("We delete the call limit")
Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, CanDeleteRateLimiting.toString)
- val deleteRequest = (v6_0_0_Request / "management" / "consumers" / consumerId / "consumer" / "call-limits" / createdCallLimit.rate_limiting_id).DELETE <@ (user1)
+ val deleteRequest = (v6_0_0_Request / "management" / "consumers" / consumerId / "consumer" / "rate-limits" / createdCallLimit.rate_limiting_id).DELETE <@ (user1)
val deleteResponse = makeDeleteRequest(deleteRequest)
Then("We should get a 204")
@@ -138,14 +139,14 @@ class CallLimitsTest extends V600ServerSetup {
Given("We create a call limit first")
val Some((c, _)) = user1
val consumerId = Consumers.consumers.vend.getConsumerByConsumerKey(c.key).map(_.consumerId.get).getOrElse("")
- Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, CanSetCallLimits.toString)
- val request600 = (v6_0_0_Request / "management" / "consumers" / consumerId / "consumer" / "call-limits").POST <@ (user1)
+ Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, CanCreateRateLimits.toString)
+ val request600 = (v6_0_0_Request / "management" / "consumers" / consumerId / "consumer" / "rate-limits").POST <@ (user1)
val createResponse = makePostRequest(request600, write(postCallLimitJsonV600))
createResponse.code should equal(201)
val createdCallLimit = createResponse.body.extract[CallLimitJsonV600]
When("We try to delete without proper role")
- val deleteRequest = (v6_0_0_Request / "management" / "consumers" / consumerId / "consumer" / "call-limits" / createdCallLimit.rate_limiting_id).DELETE <@ (user1)
+ val deleteRequest = (v6_0_0_Request / "management" / "consumers" / consumerId / "consumer" / "rate-limits" / createdCallLimit.rate_limiting_id).DELETE <@ (user1)
val deleteResponse = makeDeleteRequest(deleteRequest)
Then("We should get a 403")
@@ -160,8 +161,8 @@ class CallLimitsTest extends V600ServerSetup {
Given("We create a call limit first")
val Some((c, _)) = user1
val consumerId = Consumers.consumers.vend.getConsumerByConsumerKey(c.key).map(_.consumerId.get).getOrElse("")
- Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, CanSetCallLimits.toString)
- val request600 = (v6_0_0_Request / "management" / "consumers" / consumerId / "consumer" / "call-limits").POST <@ (user1)
+ Entitlement.entitlement.vend.addEntitlement("", resourceUser1.userId, CanCreateRateLimits.toString)
+ val request600 = (v6_0_0_Request / "management" / "consumers" / consumerId / "consumer" / "rate-limits").POST <@ (user1)
val createResponse = makePostRequest(request600, write(postCallLimitJsonV600))
createResponse.code should equal(201)
@@ -170,7 +171,7 @@ class CallLimitsTest extends V600ServerSetup {
val currentDateString = ZonedDateTime
.now(ZoneOffset.UTC)
.format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss'Z'"))
- val getRequest = (v6_0_0_Request / "management" / "consumers" / consumerId / "consumer" / "call-limits" / "active-at-date" / currentDateString).GET <@ (user1)
+ val getRequest = (v6_0_0_Request / "management" / "consumers" / consumerId / "consumer" / "rate-limits" / "active-at-date" / currentDateString).GET <@ (user1)
val getResponse = makeGetRequest(getRequest)
Then("We should get a 200")
@@ -188,7 +189,7 @@ class CallLimitsTest extends V600ServerSetup {
val currentDateString = ZonedDateTime
.now(ZoneOffset.UTC)
.format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss'Z'"))
- val getRequest = (v6_0_0_Request / "management" / "consumers" / consumerId / "consumer" / "call-limits" / "active-at-date" / currentDateString).GET <@ (user1)
+ val getRequest = (v6_0_0_Request / "management" / "consumers" / consumerId / "consumer" / "rate-limits" / "active-at-date" / currentDateString).GET <@ (user1)
val getResponse = makeGetRequest(getRequest)
Then("We should get a 403")
diff --git a/obp-api/src/test/scala/code/util/ApiSessionTest.scala b/obp-api/src/test/scala/code/util/ApiSessionTest.scala
index c0d2c0a1ed..b8eb4564d1 100644
--- a/obp-api/src/test/scala/code/util/ApiSessionTest.scala
+++ b/obp-api/src/test/scala/code/util/ApiSessionTest.scala
@@ -56,4 +56,30 @@ class ApiSessionTest extends FeatureSpec with Matchers with GivenWhenThen with M
callContextUpdated.get.sessionId should be (Some("12345"))
}
}
+
+ feature("test CallContext toString secure logging masking")
+ {
+ scenario("toString should mask sensitive data")
+ {
+ val callContextWithSensitiveData = CallContext(
+ directLoginParams = Map("password" -> "supersecret"),
+ oAuthParams = Map("client_secret" -> "my_client_secret")
+ )
+
+ val toStringResult = callContextWithSensitiveData.toString
+
+ // Verify that sensitive data is masked - should NOT contain the actual sensitive values
+ toStringResult should not contain "supersecret"
+ toStringResult should not contain "my_client_secret"
+
+ // Verify that the result contains the case class structure (not just object reference)
+ toStringResult should include("CallContext")
+
+ // Verify that masking occurs by checking for masked patterns or lack of sensitive data
+ val containsActualSensitiveData = toStringResult.contains("supersecret") ||
+ toStringResult.contains("my_client_secret")
+
+ containsActualSensitiveData should be (false)
+ }
+ }
}
\ No newline at end of file
diff --git a/obp-commons/pom.xml b/obp-commons/pom.xml
index b41909faf1..eac3d3709e 100644
--- a/obp-commons/pom.xml
+++ b/obp-commons/pom.xml
@@ -91,30 +91,7 @@
-
- org.owasp
- dependency-check-maven
- 7.1.1
-
- notifier-dependency-check
- HTML
- 10
- false
- true
-
- true
- true
- false
- pom
-
-
-
-
- aggregate
-
-
-
-
+
org.apache.maven.plugins
maven-surefire-plugin
@@ -178,4 +155,61 @@
+
+
+
+ dependency-check
+
+
+
+ env.NVD_API_KEY
+
+
+
+
+
+
+ org.owasp
+ dependency-check-maven
+ 8.4.3
+
+
+ ${env.NVD_API_KEY}
+ true
+ false
+ true
+
+ notifier-dependency-check
+ HTML
+ ${project.build.directory}/dependency-check-report
+ 10
+ false
+ true
+ true
+ true
+ pom
+
+
+ false
+ false
+ false
+ false
+ false
+ false
+
+
+
+
+ dependency-check
+ verify
+
+ check
+
+
+
+
+
+
+
+