Skip to content

Commit 80ad117

Browse files
committed
rate limits for unauthenticated
1 parent 8b51332 commit 80ad117

File tree

3 files changed

+121
-3
lines changed

3 files changed

+121
-3
lines changed

cads_processing_api_service/config.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ class RateLimitsRouteParamConfig(pydantic.BaseModel):
116116
model_config = pydantic.ConfigDict(extra="allow")
117117

118118

119-
class RateLimitsConfig(pydantic.BaseModel):
119+
class RateLimitsUserConfig(pydantic.BaseModel):
120120
default: RateLimitsRouteConfig = pydantic.Field(
121121
default=RateLimitsRouteConfig(), validate_default=True
122122
)
@@ -151,6 +151,14 @@ class RateLimitsConfig(pydantic.BaseModel):
151151
)
152152

153153

154+
class RateLimitsConfig(RateLimitsUserConfig):
155+
"""Rate limits configuration for the service."""
156+
157+
unauthenticated: RateLimitsUserConfig = pydantic.Field(
158+
default=RateLimitsUserConfig(), validate_default=True
159+
)
160+
161+
154162
def load_rate_limits(rate_limits_file: str | None) -> RateLimitsConfig:
155163
rate_limits = RateLimitsConfig()
156164
if rate_limits_file is not None:

cads_processing_api_service/limits.py

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,26 @@ def get_rate_limits_defaulted(
7070
return rate_limits
7171

7272

73+
def get_rate_limits_for_user(
74+
rate_limits_config: config.RateLimitsConfig,
75+
user_uid: str,
76+
route: str,
77+
method: str,
78+
request_origin: str,
79+
route_param: str | None = None,
80+
) -> list[str]:
81+
rate_limits = []
82+
if user_uid == "unauthenticated":
83+
rate_limits = get_rate_limits_defaulted(
84+
rate_limits_config.unauthenticated, route, method, request_origin, route_param
85+
)
86+
if not rate_limits:
87+
rate_limits = get_rate_limits_defaulted(
88+
rate_limits_config, route, method, request_origin, route_param
89+
)
90+
return rate_limits
91+
92+
7393
def check_rate_limits_for_user(
7494
user_uid: str, rate_limits: list[limits.RateLimitItem]
7595
) -> None:
@@ -104,8 +124,8 @@ def check_rate_limits(
104124
"""Check if the rate limits are exceeded."""
105125
request_origin = auth_info.request_origin
106126
user_uid = auth_info.user_uid
107-
rate_limits = get_rate_limits_defaulted(
108-
rate_limits_config, route, method, request_origin, route_param
127+
rate_limits = get_rate_limits_for_user(
128+
rate_limits_config, user_uid, route, method, request_origin, route_param
109129
)
110130
rate_limits_parsed = [limits.parse(rate_limit) for rate_limit in rate_limits]
111131
check_rate_limits_for_user(user_uid, rate_limits_parsed)

tests/test_30_limits.py

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,96 @@ def test_get_rate_limits_undefined() -> None:
190190
assert rate_limits == exp_rate_limits
191191

192192

193+
def test_get_rate_limits_for_user_unauthenticated() -> None:
194+
rate_limits = {
195+
"default": {
196+
"get": {"api": ["5/second"]},
197+
"post": {"api": ["10/second"]},
198+
},
199+
"/jobs/{job_id}": {"delete": {"api": ["1/second"]}},
200+
"unauthenticated": {
201+
"default": {"post": {"api": ["2/second"]}},
202+
"/jobs/{job_id}": {"get": {"api": ["3/second"]}}
203+
},
204+
}
205+
rate_limits_config = config.RateLimitsConfig.model_validate(rate_limits)
206+
207+
route = "jobs_jobsid"
208+
method = "get"
209+
request_origin = "api"
210+
user_uid = "unauthenticated"
211+
rate_limits = cads_processing_api_service.limits.get_rate_limits_for_user(
212+
rate_limits_config, user_uid, route, method, request_origin
213+
)
214+
exp_rate_limits = ["3/second"]
215+
assert rate_limits == exp_rate_limits
216+
217+
route = "jobs_jobsid"
218+
method = "post"
219+
request_origin = "api"
220+
user_uid = "unauthenticated"
221+
rate_limits = cads_processing_api_service.limits.get_rate_limits_for_user(
222+
rate_limits_config, user_uid, route, method, request_origin
223+
)
224+
exp_rate_limits = ["2/second"]
225+
assert rate_limits == exp_rate_limits
226+
227+
route = "jobs_jobsid"
228+
method = "delete"
229+
request_origin = "api"
230+
user_uid = "unauthenticated"
231+
rate_limits = cads_processing_api_service.limits.get_rate_limits_for_user(
232+
rate_limits_config, user_uid, route, method, request_origin
233+
)
234+
exp_rate_limits = ["1/second"]
235+
assert rate_limits == exp_rate_limits
236+
237+
238+
def test_get_rate_limits_for_user_authenticated() -> None:
239+
rate_limits = {
240+
"default": {
241+
"get": {"api": ["5/second"]},
242+
"post": {"api": ["10/second"]},
243+
},
244+
"/jobs/{job_id}": {"delete": {"api": ["1/second"]}},
245+
"unauthenticated": {
246+
"default": {"post": {"api": ["2/second"]}},
247+
"/jobs/{job_id}": {"get": {"api": ["3/second"]}}
248+
},
249+
}
250+
rate_limits_config = config.RateLimitsConfig.model_validate(rate_limits)
251+
252+
route = "jobs_jobsid"
253+
method = "get"
254+
request_origin = "api"
255+
user_uid = "user_uid"
256+
rate_limits = cads_processing_api_service.limits.get_rate_limits_for_user(
257+
rate_limits_config, user_uid, route, method, request_origin
258+
)
259+
exp_rate_limits = ["5/second"]
260+
assert rate_limits == exp_rate_limits
261+
262+
route = "jobs_jobsid"
263+
method = "post"
264+
request_origin = "api"
265+
user_uid = "user_uid"
266+
rate_limits = cads_processing_api_service.limits.get_rate_limits_for_user(
267+
rate_limits_config, user_uid, route, method, request_origin
268+
)
269+
exp_rate_limits = ["10/second"]
270+
assert rate_limits == exp_rate_limits
271+
272+
route = "jobs_jobsid"
273+
method = "delete"
274+
request_origin = "api"
275+
user_uid = "user_uid"
276+
rate_limits = cads_processing_api_service.limits.get_rate_limits_for_user(
277+
rate_limits_config, user_uid, route, method, request_origin
278+
)
279+
exp_rate_limits = ["1/second"]
280+
assert rate_limits == exp_rate_limits
281+
282+
193283
def test_check_rate_limits_for_user() -> None:
194284
rate_limit_ids = ["1/second"]
195285
rate_limits = [limits.parse(rate_limit_id) for rate_limit_id in rate_limit_ids]

0 commit comments

Comments
 (0)