Rate limiting#968
Merged
Merged
Conversation
…ocity limiting Sliding-window per-IP rate limiter with livesettings configuration: - Configurable requests/window, cache size, optional ban command - Uses X-Forwarded-For for correct IP detection behind reverse proxies - ASKBOT_INTERNAL_IPS whitelist bypasses rate limiting - Per-IP registration rate limiting on signup/register endpoints - Content velocity limiting for watched users (opt-in, default off) Rate-limited requests get a _ratelimited attribute for integration with the request logging middleware.
…ponses * Move per-IP rate-limit state from in-process dict to the Django cache so multi-process deployments share buckets; warn when the cache backend does not support shared use. * Add registration rate limiting via view-level decorators on register and signup_with_password. * Render 429 responses as HTML for browsers and JSON for AJAX/API clients, with a Retry-After header and a client-side banner that shows a humanized retry-after time. * Add new livesettings RATE_LIMIT_IP_ALLOWLIST (runtime allowlist unioned with deploy-time ASKBOT_INTERNAL_IPS) and RATE_LIMIT_SUBNET_GRANULARITY (host/subnet/region keying). * Honor CIDR ranges and IPv6 (incl. IPv4-mapped) in the closed-forum ASKBOT_INTERNAL_IPS bypass. * Emit rate-limit events as structured WARNING log lines on the askbot.utils.ratelimit logger for tailer integrations. * Add manage.py check entries that validate rate-limit settings. * Require django-ratelimit>=4.0,<5.0 and Django 4.2 LTS minimum. Includes documentation updates, a 429 template, helper utilities in askbot/utils/ratelimit.py, new tests, and refreshed translation catalogs.
Replace direct askbot_settings.update() / try-finally pairs with livesettings_override context managers so prior values are captured and restored automatically. The hardcoded restores in the old code disagreed with the actual livesetting defaults (REQUEST_RATE_LIMIT_ENABLED, REQUEST_RATE_LIMIT_MAX_REQUESTS), leaking corrupted values into later tests. Drop hardcoded restores from SubnetGranularityTests.tearDown and AllowlistTests.tearDown; with_settings / livesettings_override now handle restoration. Guard the MISCONFIG_CHECK_DONE module flag in RateLimitMisconfigWarningTests and RateLimitIntegrationTests with addCleanup so it resets to False even if a test raises, preventing leakage across class boundaries. Drop stale "Test N" marker comments and the now-misleading "retired test 7" / "Test 11" references in test_utils_ratelimit.py. Refs: askbot-master-9pu
…tests Replaces 11 ``with override_settings(...)`` / ``with livesettings_override(...)`` blocks that wrapped entire test bodies with method decorators (7 ``@override_settings`` and 4 ``@with_settings``). Pure refactor — no behavior change. Context-manager guards remain where the override references per-test locals (e.g. tmpdir) or only covers a partial block.
…messageId]); SystemMessage also receives optional message id
…ate limit Adds a `ratelimit_exempt` decorator and refactors `RateLimitMiddleware.__call__` into `process_view`, so the per-request policy short-circuits BEFORE consuming a bucket slot when the resolved view carries the exempt mark. Applied to: - `read_message` (POST /messages/markread/) — dismissing a rate-limit banner no longer spawns a new one. - `JavaScriptCatalog` (/jsi18n/) — a 429 there used to break i18n for the rest of the session. Tests: new `askbot/tests/test_ratelimit_middleware.py` covers the decorator contract, exempt bypass under a saturated bucket, the exempt-doesn't-consume-slots invariant, the canonical `@ratelimit_exempt` / `@csrf.csrf_protect` stack, non-`@wraps` inner wrappers shadowing the attribute, registration-policy orthogonality, and the `view_func=None` defensive case. End-to-end integration tests for both endpoints added to `test_rate_limiting.py`. Refs askbot-master-2c8.
…it middleware, when it is needed + test cases
… feature update; in askbot/jinja2/429.html removed link to the home page
Two new livesettings let trusted contributors skip the watched-user post rate limit while still being watched for every other purpose: RATE_LIMIT_BYPASS_HIGH_REP_USERS (master switch) and MIN_REP_TO_BYPASS_RATE_LIMIT (reputation threshold). The bypass applies only to the watched-user-post limit; the per-IP request and registration limits are unaffected.
Add ratelimit_exempt_resolver, a URLconf-level opt-out that stamps the exempt mark on every callback reachable through an included URLconf. Wire it onto the livesettings include in askbot/urls.py so the admin settings pages are never rate limited.
Move the registration rate-limit check from the view decorator into explicit per-call-site checks inside the registration views. The form-based signup paths now re-render with a feedback message, while the formless one-click path still returns the standalone 429 page.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.