diff --git a/README.md b/README.md index e42fce2..b11faaa 100644 --- a/README.md +++ b/README.md @@ -202,6 +202,7 @@ hoptchaPost('/endpoint', payload, onSuccess, onError, function renderCustom(url) | `response` | Optional custom response function on CAPTCHA failure | `None` | | `exempt_if` | Skip protection for trusted users | For staff | | `methods` | HTTP methods to track (POST, GET, etc.) | POST | +| `shared` | Share same attempts counter among all endpoints | `False` | --- diff --git a/django_hoptcha/decorators.py b/django_hoptcha/decorators.py index abf94bb..a666a39 100644 --- a/django_hoptcha/decorators.py +++ b/django_hoptcha/decorators.py @@ -56,6 +56,7 @@ def hoptcha_protected( response=None, exempt_if=lambda request: request.user.is_staff or request.user.is_superuser, backoff=False, + shared=False ): """ Enforces CAPTCHA if request exceeds `threshold`. @@ -67,7 +68,9 @@ def hoptcha_protected( - response: optional custom response function on CAPTCHA failure. - exempt_if: skip protection for trusted users. - methods: HTTP methods to track (default: POST). + - shared: Share same attempts counter among all endpoints. """ + if isinstance(key, str): key_func = BUILTIN_KEYS.get(key) if not key_func: @@ -87,6 +90,9 @@ def hoptcha_protected( return view_func(request, *args, **kwargs) user_key = key_func(request) + if not shared: + user_key = f"{user_key}:{request.path}" + cache_key = f"hoptcha-attempts:{user_key}" attempts = cache.get(cache_key, 0)