Skip to content

Cloudflare Turnstile (CAPTCHA) - #376

Open
jzgom067 wants to merge 92 commits into
v0.5.0from
captcha
Open

Cloudflare Turnstile (CAPTCHA)#376
jzgom067 wants to merge 92 commits into
v0.5.0from
captcha

Conversation

@jzgom067

Copy link
Copy Markdown
Member

This PR adds CAPTCHA to the site, in the form of Cloudflare Turnstile. I chose that solution over reCAPTCHA and hCAPTCHA because of the unlimited free use and focus on privacy.

@require_captcha Decorator

This decorator can be added to any endpoint to require a CAPTCHA token before processing any data. This decorator will send the token from the client to an endpoint on Cloudflare's servers. If the token is not supplied or invalid, an error is returned with a relevant message.

This was applied to:

  • /auth/register/
  • /auth/start-password-reset/
  • /availability/add/
  • /event/date-create/
  • /event/week-create/

.env Updates

The site key and secret key were added to the frontend and backend .env.example files, respectively. These values are used by Cloudflare to identify our project and validate users. The placeholders in .env.example are development keys that automatically verify users.

New Captcha Component

This component serves a few different purposes:

  • First, it contains the component from the newly installed package that handles the logic for talking to Cloudflare's servers and getting a token for the user.
  • Second, the component will turn into a banner if there was an issue on initialization, running a callback function that I've set to disable submission on forms. This could happen if the user has an aggressive ad blocker or a niche private browser.
    • Changing the site key in the frontend .env to a random string will trigger this.
  • Third, the component will show a dialog/drawer if the verification failed on the backend, telling the user to check the box and retry. This happens if Cloudflare isn't really sure that the user is a human, so a second attempt could prove it by gathering a bit more data like mouse movement.
    • Changing the secret key in the backend .env to a random string will trigger this.

The experience should be no different than it is now, assuming the user passes the challenge. This CAPTCHA challenge operates completely in the background until something fails.

Loosened Account Creation Rate Limits

Now that we have CAPTCHA, it reduces the risk of bots spamming our servers. We're now able to loosen the rate limits so more human users can create accounts at once.

New ApiErrorData Property

A new property was added, captchaFailed, which checks if the error messages include the string returned from the @require_captcha decorator. I know it's not the most ideal solution, but later I plan to introduce some sort of error code structure to backend error responses and this will be resolved.

New Packages

The frontend got the @marsidev/react-turnstile package, which is a community-made widget that makes using Cloudflare Turnstile really easy.

The backend got the requests package to make requests that test client tokens against Cloudflare's servers.

Backend Docs Updates

A new property, captcha_required, was added to each endpoint to denote if a CAPTCHA token is required.

The UUIDField was also given support since I forgot to fix this earlier and I couldn't test the docs endpoint without it. I also fixed this in a different branch, but it should resolve fine when merged.

This PR must be merged after #365.

@jzgom067 jzgom067 added this to the v0.5.0 milestone Jul 14, 2026
@jzgom067 jzgom067 added enhancement New feature or request cleanup Involves refactoring or small changes frontend Related to frontend stuff labels Jul 14, 2026
@coderabbitai

coderabbitai Bot commented Jul 14, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

The pull request adds Cloudflare Turnstile verification to registration, password reset, event creation, and availability submission flows. It introduces guest-import APIs and frontend pages for reviewing and transferring guest events and participations, including conflict resolution. User events gain unique public UUIDs through staged migrations. Frontend API types, protected routes, navigation, dialogs, loading states, and guest-mode messaging are updated to support these flows.

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 Checkov (3.3.8)
backend/requirements.txt

Traceback (most recent call last):
File "/usr/local/bin/checkov", line 2, in
from checkov.main import Checkov
File "/usr/local/lib/python3.11/dist-packages/checkov/main.py", line 22, in
from checkov.ansible.runner import Runner as ansible_runner
File "/usr/local/lib/python3.11/dist-packages/checkov/ansible/runner.py", line 9, in
from checkov.ansible.graph_builder.local_graph import AnsibleLocalGraph
File "/usr/local/lib/python3.11/dist-packages/checkov/ansible/graph_builder/local_graph.py", line 14, in
from checkov.ansible.utils import get_scannable_file_paths, TASK_RESERVED_KEYWORDS, parse_file
File "/usr/local/lib/python3.11/dist-packages/checkov/ansible/utils.py", line 13, in
from checkov.common.runners.base_runner import filter_ignored_paths
File "/usr/local/lib/python3.11/dist-packages/checkov/common/runners/base_runner.py", line 17, in
from checkov.common.output.report import Report
File "

... [truncated 567 characters] ...

pydantic/init.py", line 5, in
from ._migration import getattr_migration
File "/usr/local/lib/python3.11/dist-packages/pydantic/_migration.py", line 4, in
from pydantic.warnings import PydanticDeprecatedSince20
File "/usr/local/lib/python3.11/dist-packages/pydantic/warnings.py", line 5, in
from .version import version_short
File "/usr/local/lib/python3.11/dist-packages/pydantic/version.py", line 7, in
from pydantic_core import version as pydantic_core_version
File "/usr/local/lib/python3.11/dist-packages/pydantic_core/init.py", line 6, in
from typing_extensions import Sentinel
ImportError: cannot import name 'Sentinel' from 'typing_extensions' (/.local/lib/python3.11/site-packages/typing_extensions.py)

frontend/package.json

Traceback (most recent call last):
File "/usr/local/bin/checkov", line 2, in
from checkov.main import Checkov
File "/usr/local/lib/python3.11/dist-packages/checkov/main.py", line 22, in
from checkov.ansible.runner import Runner as ansible_runner
File "/usr/local/lib/python3.11/dist-packages/checkov/ansible/runner.py", line 9, in
from checkov.ansible.graph_builder.local_graph import AnsibleLocalGraph
File "/usr/local/lib/python3.11/dist-packages/checkov/ansible/graph_builder/local_graph.py", line 14, in
from checkov.ansible.utils import get_scannable_file_paths, TASK_RESERVED_KEYWORDS, parse_file
File "/usr/local/lib/python3.11/dist-packages/checkov/ansible/utils.py", line 13, in
from checkov.common.runners.base_runner import filter_ignored_paths
File "/usr/local/lib/python3.11/dist-packages/checkov/common/runners/base_runner.py", line 17, in
from checkov.common.output.report import Report
File "

... [truncated 567 characters] ...

pydantic/init.py", line 5, in
from ._migration import getattr_migration
File "/usr/local/lib/python3.11/dist-packages/pydantic/_migration.py", line 4, in
from pydantic.warnings import PydanticDeprecatedSince20
File "/usr/local/lib/python3.11/dist-packages/pydantic/warnings.py", line 5, in
from .version import version_short
File "/usr/local/lib/python3.11/dist-packages/pydantic/version.py", line 7, in
from pydantic_core import version as pydantic_core_version
File "/usr/local/lib/python3.11/dist-packages/pydantic_core/init.py", line 6, in
from typing_extensions import Sentinel
ImportError: cannot import name 'Sentinel' from 'typing_extensions' (/.local/lib/python3.11/site-packages/typing_extensions.py)


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 11


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 4a1468eb-c303-4a6d-8894-b391778227aa

📥 Commits

Reviewing files that changed from the base of the PR and between b78dbfd and 236d502.

⛔ Files ignored due to path filters (1)
  • frontend/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (56)
  • backend/.env.example
  • backend/api/auth/views.py
  • backend/api/availability/views.py
  • backend/api/decorators.py
  • backend/api/docs/utils.py
  • backend/api/docs/views.py
  • backend/api/event/utils.py
  • backend/api/event/views.py
  • backend/api/guest_import/serializers.py
  • backend/api/guest_import/urls.py
  • backend/api/guest_import/utils.py
  • backend/api/guest_import/views.py
  • backend/api/migrations/0034_userevent_public_id.py
  • backend/api/migrations/0035_populate_public_id.py
  • backend/api/migrations/0036_apply_unique_constraint.py
  • backend/api/models.py
  • backend/api/settings.py
  • backend/api/urls.py
  • backend/api/utils.py
  • backend/requirements.txt
  • frontend/.env.example
  • frontend/package.json
  • frontend/src/app/(auth)/forgot-password/page.tsx
  • frontend/src/app/(auth)/login/page.tsx
  • frontend/src/app/(auth)/register/page.tsx
  • frontend/src/app/(event)/[event-code]/painting/page-client.tsx
  • frontend/src/app/dashboard/page-client.tsx
  • frontend/src/app/guest-import/import/loading.tsx
  • frontend/src/app/guest-import/import/page-client.tsx
  • frontend/src/app/guest-import/import/page.tsx
  • frontend/src/app/guest-import/layout.tsx
  • frontend/src/app/guest-import/login/page-client.tsx
  • frontend/src/app/guest-import/login/page.tsx
  • frontend/src/app/settings/(submenus)/guest-import/page.tsx
  • frontend/src/app/settings/loading.tsx
  • frontend/src/components/captcha.tsx
  • frontend/src/components/layout/message-page.tsx
  • frontend/src/features/account/setting-dialogs/change-password/main-dialog.tsx
  • frontend/src/features/account/setting-dialogs/delete-account.tsx
  • frontend/src/features/account/settings/sidebar-nav.tsx
  • frontend/src/features/drawer/components/base.tsx
  • frontend/src/features/event/editor/editor.tsx
  • frontend/src/features/guest-import/components/guest-summary.tsx
  • frontend/src/features/guest-import/constants.ts
  • frontend/src/features/selector/components/drawer.tsx
  • frontend/src/features/system-feedback/dialog/components/base.tsx
  • frontend/src/features/system-feedback/dialog/components/confirmation.tsx
  • frontend/src/features/system-feedback/dialog/components/form.tsx
  • frontend/src/features/system-feedback/dialog/props.ts
  • frontend/src/features/system-feedback/toast/context.ts
  • frontend/src/lib/messages.ts
  • frontend/src/lib/utils/api/endpoints.ts
  • frontend/src/lib/utils/api/fetch-wrapper.ts
  • frontend/src/lib/utils/api/submit-event.ts
  • frontend/src/lib/utils/api/types.ts
  • frontend/src/middleware.ts
💤 Files with no reviewable changes (1)
  • frontend/src/features/account/setting-dialogs/change-password/main-dialog.tsx

Comment thread backend/api/decorators.py Outdated
Comment thread backend/api/guest_import/views.py
Comment thread backend/api/guest_import/views.py
Comment thread frontend/src/app/(auth)/login/page.tsx
Comment thread frontend/src/app/guest-import/import/page-client.tsx
Comment thread frontend/src/components/captcha.tsx
Comment thread frontend/src/features/guest-import/components/guest-summary.tsx
Comment thread frontend/src/features/system-feedback/dialog/components/form.tsx
Comment thread frontend/src/lib/utils/api/fetch-wrapper.ts Outdated
Comment thread frontend/src/lib/utils/api/submit-event.ts Outdated
@jzgom067
jzgom067 requested a review from mirmirmirr July 14, 2026 23:03
@jzgom067 jzgom067 added the backend Related to backend stuff label Jul 15, 2026
@jzgom067 jzgom067 linked an issue Jul 26, 2026 that may be closed by this pull request
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend Related to backend stuff cleanup Involves refactoring or small changes enhancement New feature or request frontend Related to frontend stuff

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add CAPTCHA to the site

1 participant