Skip to content

fix(api_views): remove throttles and add auth classes to webhook api#7453

Merged
albertisfu merged 4 commits into
mainfrom
remove-webhooks-api-from-rate-limits
Jun 18, 2026
Merged

fix(api_views): remove throttles and add auth classes to webhook api#7453
albertisfu merged 4 commits into
mainfrom
remove-webhooks-api-from-rate-limits

Conversation

@nadahlberg

Copy link
Copy Markdown
Member

Fixes

Fixes #7452

Summary

Disable throttling on the webhook UI viewsets (WebhooksViewSet, WebhookEventViewSet) so visiting the webhooks tab no longer counts against or gets blocked by the user's API rate limit. To offset the removed throttle, restrict these endpoints to session-only authentication (ReplicaRoutingSessionAuthentication) so they can't be hit by token-based clients.

Deployment

This PR should:

  • skip-deploy (skips everything below)
    • skip-web-deploy
    • skip-celery-deploy
    • skip-cronjob-deploy
    • skip-daemon-deploy

Comment thread cl/users/api_views.py
Comment on lines +33 to +34
authentication_classes = [ReplicaRoutingSessionAuthentication]
throttle_classes = []

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 Restricting these viewsets to [ReplicaRoutingSessionAuthentication] replaces (not extends) DRF's default auth classes, so Token auth is no longer accepted. The existing WebhooksHTMXTests suite in cl/users/tests.py (line 3546) uses make_client() from cl/tests/utils.py:107-113, which authenticates exclusively via the Authorization: Token <token> header and never establishes a Django session — so all ~9 tests in that class (test_make_an_webhook, test_make_an_http_webhook_fails, test_list_users_webhooks, test_delete_webhook, test_webhook_detail, test_webhook_update, test_send_webhook_test, test_send_webhook_test_all_types, test_list_webhook_events) will return 401/403 and CI will break. Fix by migrating those tests to a session-authenticated client (e.g. client.force_login / APIClient.force_authenticate) alongside this PR.

Extended reasoning...

What the bug is

DRF's authentication_classes on a view replaces DEFAULT_AUTHENTICATION_CLASSES rather than appending to them. Before this PR, WebhooksViewSet and WebhookEventViewSet inherited the project defaults from cl/settings/third_party/rest_framework.py (Token, OAuth2, Basic, Session). After this PR they accept only ReplicaRoutingSessionAuthentication, which extends DRF SessionAuthentication (cl/api/authentication.py:100) and only authenticates via the Django session cookie — it ignores Authorization: Token … headers entirely.

The test path that breaks

WebhooksHTMXTests (cl/users/tests.py:3546) builds its clients in setUp:

self.client = make_client(self.user_1.pk)
self.client_2 = make_client(self.user_2.pk)

make_client (cl/tests/utils.py:107-113) is the only authentication step:

def make_client(user_pk: int) -> AsyncAPIClient:
    user = User.objects.get(pk=user_pk)
    token, created = Token.objects.get_or_create(user=user)
    token_header = f"Token {token}"
    client = AsyncAPIClient()
    client.credentials(HTTP_AUTHORIZATION=token_header)
    return client

No login, no force_login, no session cookie — just the Token header.

Step-by-step proof that test_make_an_webhook will fail

  1. setUp runs self.client = make_client(self.user_1.pk)AsyncAPIClient with only HTTP_AUTHORIZATION: Token <token> set.
  2. test_make_an_webhook calls self.make_a_webhook(self.client)POST /…webhooks-list….
  3. DRF dispatches to WebhooksViewSet; with this PR, authentication_classes = [ReplicaRoutingSessionAuthentication] is the only class consulted.
  4. ReplicaRoutingSessionAuthentication (subclass of SessionAuthentication) reads request._request.user from the session middleware. No session cookie is present, so request.user resolves to AnonymousUser and authenticate() returns None. The Authorization: Token <token> header is never inspected because TokenAuthentication is no longer in the list.
  5. IsAuthenticated rejects → DRF returns 401 Unauthorized.
  6. The test asserts response.status_code == HTTPStatus.CREATED (201) → AssertionError, CI fails.

Why the existing code doesn't protect against this

The PR diff only touches cl/users/api_views.py; no companion update to cl/users/tests.py and no override of setUp to establish a session. All nine listed tests (test_make_an_webhook, test_make_an_http_webhook_fails, test_list_users_webhooks, test_delete_webhook, test_webhook_detail, test_webhook_update, test_send_webhook_test, test_send_webhook_test_all_types, test_list_webhook_events) follow the same pattern: they assert HTTPStatus.OK / CREATED / NO_CONTENT / NOT_FOUND and will all instead receive 401/403.

Impact and fix

This is a hard CI break on merge — every test in WebhooksHTMXTests flips red. The fix is to switch the test client to session auth. Either replace make_client(user.pk) with an AsyncAPIClient() and call await sync_to_async(client.force_login)(user) in setUp, or use client.force_authenticate(user=user). (The product intent — that these UI viewsets are only callable via the logged-in browser session — is correct; only the tests need updating.)

@nadahlberg

Copy link
Copy Markdown
Member Author

@albertisfu this implements a fix to the webhooks issue based on your suggestions in the (now-closed) PR #7340. That PR is blocked for unrelated reasons, so I'm breaking this out as a separate issue.

This adds the throttle_classes = [] and ReplicaRoutingSessionAuthentication to the webhooks endpoint. And it adds a small helper for session-based test clients and updates the webhook endpoint tests to use it.

@nadahlberg nadahlberg requested a review from albertisfu June 16, 2026 16:57
@nadahlberg nadahlberg assigned albertisfu and unassigned nadahlberg Jun 16, 2026
@mlissner mlissner moved this to To Do in Sprint (Web Team) Jun 16, 2026
@albertisfu albertisfu moved this from To Do to In progress in Sprint (Web Team) Jun 17, 2026

@albertisfu albertisfu left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @nadahlberg this is working as expected. Merging...

@albertisfu albertisfu enabled auto-merge June 17, 2026 20:43
@albertisfu albertisfu merged commit 8947173 into main Jun 18, 2026
9 checks passed
@albertisfu albertisfu deleted the remove-webhooks-api-from-rate-limits branch June 18, 2026 14:33
@github-project-automation github-project-automation Bot moved this from In progress to Done in Sprint (Web Team) Jun 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

Webhooks UI endpoints count against API rate limits

3 participants