Skip to content

Commit 1e59bd8

Browse files
authored
Merge pull request #2625 from constantine2nd/develop
New endpoints for Rate Limiting
2 parents 33de87c + c2e43a2 commit 1e59bd8

22 files changed

+538
-250
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -557,8 +557,8 @@ user_consumer_limit_anonymous_access=100, In case isn't defined default value is
557557
558558
Te set up Rate Limiting in case of the authorized access use these endpoints:
559559
560-
1. `GET ../management/consumers/CONSUMER_ID/consumer/call-limits` - Get Call Limits for a Consumer
561-
2. `PUT ../management/consumers/CONSUMER_ID/consumer/call-limits` - Set Call Limits for a Consumer
560+
1. `GET ../management/consumers/CONSUMER_ID/consumer/rate-limits` - Get Rate Limits for a Consumer
561+
2. `PUT ../management/consumers/CONSUMER_ID/consumer/rate-limits` - Set Rate Limits for a Consumer
562562
563563
In order to make it work edit your props file in next way:
564564

completed_developments.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ Consent
137137

138138
Consumer
139139

140-
Get Call Limits for a Consumer
140+
Get Rate Limits for a Consumer
141141
Get Consumer
142142
Get Consumers
143143
Get Consumers (logged in User)

obp-api/src/main/scala/code/api/util/APIUtil.scala

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3119,7 +3119,10 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{
31193119
} // Direct Login Deprecated i.e Authorization: DirectLogin token=eyJhbGciOiJIUzI1NiJ9.eyIiOiIifQ.Y0jk1EQGB4XgdqmYZUHT6potmH3mKj5mEaA9qrIXXWQ
31203120
else if (getPropsAsBoolValue("allow_direct_login", true) && hasDirectLoginHeader(cc.authReqHeaderField) && !url.contains("/my/logins/direct")) {
31213121
DirectLogin.getUserFromDirectLoginHeaderFuture(cc)
3122-
} else if (getPropsAsBoolValue("allow_direct_login", true) &&
3122+
}
3123+
// Endpoint /my/logins/direct is onboarding endpoint for Direct Login Flow authentication
3124+
// You POST your credentials (username, password, and consumer key) to the DirectLogin endpoint and receive a token in return.
3125+
else if (getPropsAsBoolValue("allow_direct_login", true) &&
31233126
(has2021DirectLoginHeader(cc.requestHeaders) || hasDirectLoginHeader(cc.authReqHeaderField)) &&
31243127
url.contains("/my/logins/direct")) {
31253128
Future{(Empty, Some(cc))}

obp-api/src/main/scala/code/api/util/AfterApiAuth.scala

Lines changed: 35 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -96,38 +96,47 @@ object AfterApiAuth extends MdcLoggable{
9696
* Please note that first source is the table RateLimiting and second is the table Consumer
9797
*/
9898
def checkRateLimiting(userIsLockedOrDeleted: Future[(Box[User], Option[CallContext])]): Future[(Box[User], Option[CallContext])] = {
99-
def getRateLimiting(consumerId: String, version: String, name: String): Future[Box[RateLimiting]] = {
99+
def getActiveRateLimitings(consumerId: String): Future[List[RateLimiting]] = {
100100
RateLimitingUtil.useConsumerLimits match {
101-
case true => RateLimitingDI.rateLimiting.vend.getByConsumerId(consumerId, version, name, Some(new Date()))
102-
case false => Future(Empty)
101+
case true => RateLimitingDI.rateLimiting.vend.getActiveCallLimitsByConsumerIdAtDate(consumerId, new Date())
102+
case false => Future(List.empty)
103103
}
104104
}
105+
106+
def aggregateLimits(limits: List[RateLimiting], consumerId: String): CallLimit = {
107+
def sumLimits(values: List[Long]): Long = {
108+
val positiveValues = values.filter(_ > 0)
109+
if (positiveValues.isEmpty) -1 else positiveValues.sum
110+
}
111+
112+
if (limits.nonEmpty) {
113+
CallLimit(
114+
consumerId,
115+
limits.find(_.apiName.isDefined).flatMap(_.apiName),
116+
limits.find(_.apiVersion.isDefined).flatMap(_.apiVersion),
117+
limits.find(_.bankId.isDefined).flatMap(_.bankId),
118+
sumLimits(limits.map(_.perSecondCallLimit)),
119+
sumLimits(limits.map(_.perMinuteCallLimit)),
120+
sumLimits(limits.map(_.perHourCallLimit)),
121+
sumLimits(limits.map(_.perDayCallLimit)),
122+
sumLimits(limits.map(_.perWeekCallLimit)),
123+
sumLimits(limits.map(_.perMonthCallLimit))
124+
)
125+
} else {
126+
CallLimit(consumerId, None, None, None, -1, -1, -1, -1, -1, -1)
127+
}
128+
}
129+
105130
for {
106131
(user, cc) <- userIsLockedOrDeleted
107132
consumer = cc.flatMap(_.consumer)
108-
version = cc.map(_.implementedInVersion).getOrElse("None") // Calculate apiVersion in case of Rate Limiting
109-
operationId = cc.flatMap(_.operationId) // Unique Identifier of Dynamic Endpoints
110-
// Calculate apiName in case of Rate Limiting
111-
name = cc.flatMap(_.resourceDocument.map(_.partialFunctionName)) // 1st try: function name at resource doc
112-
.orElse(operationId) // 2nd try: In case of Dynamic Endpoint we can only use operationId
113-
.getOrElse("None") // Not found any unique identifier
114-
rateLimiting <- getRateLimiting(consumer.map(_.consumerId.get).getOrElse(""), version, name)
133+
consumerId = consumer.map(_.consumerId.get).getOrElse("")
134+
rateLimitings <- getActiveRateLimitings(consumerId)
115135
} yield {
116-
val limit: Option[CallLimit] = rateLimiting match {
117-
case Full(rl) => Some(CallLimit(
118-
rl.consumerId,
119-
rl.apiName,
120-
rl.apiVersion,
121-
rl.bankId,
122-
rl.perSecondCallLimit,
123-
rl.perMinuteCallLimit,
124-
rl.perHourCallLimit,
125-
rl.perDayCallLimit,
126-
rl.perWeekCallLimit,
127-
rl.perMonthCallLimit))
128-
case Empty =>
136+
val limit: Option[CallLimit] = rateLimitings match {
137+
case Nil => // No rate limiting records found, use consumer defaults
129138
Some(CallLimit(
130-
consumer.map(_.consumerId.get).getOrElse(""),
139+
consumerId,
131140
None,
132141
None,
133142
None,
@@ -138,7 +147,8 @@ object AfterApiAuth extends MdcLoggable{
138147
consumer.map(_.perWeekCallLimit.get).getOrElse(-1),
139148
consumer.map(_.perMonthCallLimit.get).getOrElse(-1)
140149
))
141-
case _ => None
150+
case activeLimits => // Aggregate multiple rate limiting records
151+
Some(aggregateLimits(activeLimits, consumerId))
142152
}
143153
(user, cc.map(_.copy(rateLimiting = limit)))
144154
}

0 commit comments

Comments
 (0)