aiteamutils 0.2.35__py3-none-any.whl → 0.2.37__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
aiteamutils/security.py
CHANGED
@@ -6,6 +6,7 @@ from fastapi import Request, HTTPException, status
|
|
6
6
|
from functools import wraps
|
7
7
|
from jose import jwt, JWTError
|
8
8
|
from passlib.context import CryptContext
|
9
|
+
import logging
|
9
10
|
|
10
11
|
from .exceptions import CustomException, ErrorCode
|
11
12
|
from .database import DatabaseService
|
@@ -14,6 +15,9 @@ from .config import get_settings
|
|
14
15
|
|
15
16
|
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
|
16
17
|
|
18
|
+
# 전역 rate limit 상태 저장
|
19
|
+
_rate_limits: Dict[str, Dict[str, Any]] = {}
|
20
|
+
|
17
21
|
class RateLimitExceeded(CustomException):
|
18
22
|
"""Rate limit 초과 예외."""
|
19
23
|
|
@@ -199,11 +203,11 @@ def rate_limit(
|
|
199
203
|
key_func: Optional[Callable] = None
|
200
204
|
):
|
201
205
|
"""Rate limiting 데코레이터."""
|
202
|
-
rate_limits: Dict[str, Dict[str, Any]] = {}
|
203
|
-
|
204
206
|
def decorator(func: Callable) -> Callable:
|
205
207
|
@wraps(func)
|
206
208
|
async def wrapper(*args, **kwargs):
|
209
|
+
logging.info(f"[rate_limit] Starting rate limit check for {func.__name__}")
|
210
|
+
|
207
211
|
# Request 객체 찾기
|
208
212
|
request = None
|
209
213
|
for arg in args:
|
@@ -216,6 +220,7 @@ def rate_limit(
|
|
216
220
|
request = arg
|
217
221
|
break
|
218
222
|
if not request:
|
223
|
+
logging.error("[rate_limit] Request object not found in args or kwargs")
|
219
224
|
raise CustomException(
|
220
225
|
ErrorCode.INTERNAL_ERROR,
|
221
226
|
detail="Request object not found",
|
@@ -229,22 +234,27 @@ def rate_limit(
|
|
229
234
|
client_ip = request.client.host
|
230
235
|
rate_limit_key = f"rate_limit:{client_ip}:{func.__name__}"
|
231
236
|
|
237
|
+
logging.info(f"[rate_limit] Rate limit key: {rate_limit_key}")
|
238
|
+
|
232
239
|
now = datetime.now(UTC)
|
233
240
|
|
234
241
|
# 현재 rate limit 정보 가져오기
|
235
|
-
rate_info =
|
242
|
+
rate_info = _rate_limits.get(rate_limit_key)
|
243
|
+
logging.info(f"[rate_limit] Current rate info: {rate_info}")
|
236
244
|
|
237
245
|
if rate_info is None or (now - rate_info["start_time"]).total_seconds() >= window_seconds:
|
238
246
|
# 새로운 rate limit 설정
|
239
|
-
|
247
|
+
_rate_limits[rate_limit_key] = {
|
240
248
|
"count": 1,
|
241
249
|
"start_time": now
|
242
250
|
}
|
251
|
+
logging.info(f"[rate_limit] Created new rate limit: {_rate_limits[rate_limit_key]}")
|
243
252
|
else:
|
244
253
|
# 기존 rate limit 업데이트
|
245
254
|
if rate_info["count"] >= max_requests:
|
246
255
|
# rate limit 초과
|
247
256
|
remaining_seconds = window_seconds - (now - rate_info["start_time"]).total_seconds()
|
257
|
+
logging.warning(f"[rate_limit] Rate limit exceeded. Remaining seconds: {remaining_seconds}")
|
248
258
|
raise RateLimitExceeded(
|
249
259
|
detail=rate_limit_key,
|
250
260
|
source_function=func.__name__,
|
@@ -253,22 +263,25 @@ def rate_limit(
|
|
253
263
|
window_seconds=window_seconds
|
254
264
|
)
|
255
265
|
rate_info["count"] += 1
|
266
|
+
logging.info(f"[rate_limit] Updated rate info: {rate_info}")
|
256
267
|
|
257
268
|
try:
|
258
|
-
|
259
|
-
|
269
|
+
logging.info(f"[rate_limit] Executing original function: {func.__name__}")
|
270
|
+
result = await func(*args, **kwargs)
|
271
|
+
logging.info("[rate_limit] Function executed successfully")
|
272
|
+
return result
|
260
273
|
except CustomException as e:
|
261
|
-
|
274
|
+
logging.error(f"[rate_limit] CustomException occurred: {str(e)}")
|
262
275
|
raise e
|
263
276
|
except Exception as e:
|
264
|
-
|
277
|
+
logging.error(f"[rate_limit] Unexpected error occurred: {str(e)}")
|
265
278
|
raise CustomException(
|
266
279
|
ErrorCode.INTERNAL_ERROR,
|
267
280
|
detail=str(e),
|
268
281
|
source_function=func.__name__,
|
269
282
|
original_error=e
|
270
283
|
)
|
271
|
-
|
284
|
+
|
272
285
|
return wrapper
|
273
286
|
return decorator
|
274
287
|
|
aiteamutils/version.py
CHANGED
@@ -1,2 +1,2 @@
|
|
1
1
|
"""버전 정보"""
|
2
|
-
__version__ = "0.2.
|
2
|
+
__version__ = "0.2.37"
|
@@ -8,9 +8,9 @@ aiteamutils/database.py,sha256=CaH73g8PPNcmLCz4Xr0DBtNSrLcpRlyt0F1zO5Tigfo,33811
|
|
8
8
|
aiteamutils/dependencies.py,sha256=GgN8sFM7qGNmOfpLaFrhuHOgPlBVXWrEgxv29jxjEgI,4226
|
9
9
|
aiteamutils/enums.py,sha256=ipZi6k_QD5-3QV7Yzv7bnL0MjDz-vqfO9I5L77biMKs,632
|
10
10
|
aiteamutils/exceptions.py,sha256=YV-ISya4wQlHk4twvGo16I5r8h22-tXpn9wa-b3WwDM,15231
|
11
|
-
aiteamutils/security.py,sha256=
|
11
|
+
aiteamutils/security.py,sha256=9gvEqDtE3RJaoCWqELPCjkg-IsSqZVrpMP6XPZaodWU,16024
|
12
12
|
aiteamutils/validators.py,sha256=3N245cZFjgwtW_KzjESkizx5BBUDaJLbbxfNO4WOFZ0,7764
|
13
|
-
aiteamutils/version.py,sha256=
|
14
|
-
aiteamutils-0.2.
|
15
|
-
aiteamutils-0.2.
|
16
|
-
aiteamutils-0.2.
|
13
|
+
aiteamutils/version.py,sha256=CmXYar-ylEXzX7J29Pftix8-ss-hnVGdG7rr9Oikfq0,42
|
14
|
+
aiteamutils-0.2.37.dist-info/METADATA,sha256=TBQe6PWAOtODst1zDCR506fxkYQv-V4nWEo4yhAon08,1718
|
15
|
+
aiteamutils-0.2.37.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
16
|
+
aiteamutils-0.2.37.dist-info/RECORD,,
|
File without changes
|