Repository navigation
Callbacks
Use import paths in COMMENTAIL; see Configuration. Avoid slow
remote work in render callbacks. No callback should return credentials or private text.
-
CAPTCHA_BACKEND: an import path to a class with no-argument construction.create(request, site) -> CaptchaTaskandverify(request, site, challenge_id: str, answer: str) -> bool. ImportCaptchaTaskfromcommentail.security:idis a string/UUID identifier (up to 255 characters),templateis a resolvable template name,datais a dictionary of public string values. Keep answers/private provider state on the server. The template receivescaptcha.data; its form control submitsanswer. The library issues a separate browser ID and sends the original provider ID only to verification. Site/session binding, expiry, attempts, refresh invalidation, creation quotas and successful single use remain enforced by the library. The backend owns expiry/cleanup of any separate private provider state. Changing the backend invalidates prior tasks; provider errors fail closed with neutral UI messages.Noneuses arithmetic. -
GET_AVATAR:get_avatar(context, request) -> str | None, returning an image URL or using generated initials/gradient. FrozenCommentContextcontainsid,display_name,user,site,target, without guest email/internal Comment. -
GET_AUTHOR_NAME:get_author_name(user, request) -> str, for the registered author's current name. Name/avatar failures fall back to library defaults. -
GET_COMMENT_TEMPLATES:get_comment_templates(page, request) -> list[str], enumerating dynamic dependencies. Presence of the widget tag still controls connection. Resolver failures are diagnosed without breaking the page editor. -
CAN_SEND_GUEST_EMAIL:can_send_guest_email(recipient, target, site) -> bool, proving guest access to restricted pages and registered non-Page objects without a browser request. A failure denies delivery and becomes a job error.GuestRecipientcontainsemail,name,confirmed_at; the latter can beNonefor verification mail.
from django.http import HttpRequest
from commentail.avatars import CommentContext
def get_avatar(context: CommentContext, request: HttpRequest) -> str | None:
if context.user is None:
return None
profile = getattr(context.user, "profile", None)
image = getattr(profile, "avatar", None)
return image.url if image else NoneAdapt attributes to your user model. None uses deterministic initials/gradient;
callback errors fall back. The enhanced widget shows initials for broken image URLs.
Guest email is not in the context. Registered names are current; guest names stay
as submitted.
Return template-name strings such as articles/discussion.html from
GET_COMMENT_TEMPLATES(page, request). The actual template still needs the widget
tag; the callback does not enable comments by itself.
CAN_SEND_GUEST_EMAIL must prove recipient access without a browser session.
Return False unless your entitlement rules authorize the recipient for this exact
target and Site. Do not use unconditional True for private content. Public Pages
need no special callback; registered non-Page objects require it for guest mail.
The default remains local arithmetic, with no external requests or JavaScript requirement. Opt into Google reCAPTCHA v2 checkbox (not v3/Enterprise), or Yandex SmartCaptcha standard widget, in Python settings:
import os
COMMENTAIL = {
"default": {
"CAPTCHA_BACKEND": "commentail.captcha_providers.GoogleRecaptcha",
"CAPTCHA_OPTIONS": {
"site_key": os.environ["CAPTCHA_SITE_KEY"],
"secret_key": os.environ["CAPTCHA_SECRET_KEY"],
"timeout": 3,
},
},
}For Yandex use commentail.captcha_providers.YandexSmartCaptcha. Create the
matching key type with the provider and register your actual site domains.
Settings can be overridden by Site hostname as usual. CAPTCHA_OPTIONS is
replaced as a whole in a hostname section; provide both keys there. Never put
secret keys in templates, source control or client JavaScript.
The bundled script loads the selected provider only when a challenge is shown, mounts independent widgets after form/reply updates, clears expired/error tokens, and releases widgets when forms are removed. An incomplete check keeps the draft local when enhanced JavaScript is active. External widgets have no routine Refresh task button; Retry check appears after a loading or runtime error and preserves the draft. Expired checks use the provider widget again. Load Commentail's JavaScript even with ordinary HTML form submission: external widgets require it.
Both adapters verify tokens over fixed HTTPS endpoints, with a 1–10 second socket
timeout (default 3), bounded response/token size and no redirects. Google checks
boolean success and the request hostname; Yandex checks status=ok and the exact
request host, including non-default port. Empty/mismatched host claims fail.
Optional client-IP parameters are omitted. A provider outage never disables
verification or switches to arithmetic. Drafts remain editable during an outage.
Without JavaScript, a required external challenge prevents submission. The form
explains that the visitor must enable JavaScript in their browser, complete the
check, then send the comment. There is no arithmetic, email-only or additional
moderation-queue fallback: it would provide a weaker admission path and add mail
or moderation load. Existing adaptive remembered-email exemptions still apply;
disabling JavaScript grants no exemption. Provider tokens
are independently single-use and expire according to the provider's rules. The
local Google/Yandex challenge binding lasts FORM_TICKET_SECONDS (one hour by
default), so time spent writing before solving the widget does not consume a
five-minute CAPTCHA deadline. No background renewal requests are made. Arithmetic
and custom backends retain CAPTCHA_SECONDS.
External providers process browser data under their own terms. Configure site
privacy disclosures and CSP using the chosen provider's current documentation;
do not disable CSP. Google starts at www.google.com/www.gstatic.com, Yandex
at smartcaptcha.cloud.yandex.ru; allow the required script/frame/connect sources.
Automated tests use mocked responses, not real keys or external verification.
Protocols: Google display, Google verification, Yandex widgets, Yandex verification.
The bundled forms issue independent challenges. Opening another tab does not
revoke an existing proof; refresh invalidates only the submitted challenge in
the same browser/Site. Direct create_captcha(request, site) callers retain the
legacy session-wide replacement; replace_id="" creates an independent task,
and an explicit replace_id refreshes that task. Backends themselves retain
the same create/verify signatures.
Implement a no-argument backend with the documented create/verify methods. The
public template posts answer and preserves the hidden challenge field. Keep all
solutions and private provider state server-side. Library proof constraints wrap
custom backends; your backend cleans up its own extra state. A backend change
invalidates previously issued tasks. Arithmetic CAPTCHA alone is not strong bot detection.
- Home
- Главная на русском
- Course in English
- Курс на русском
- Installation
- Configuration
- Moderation
- Rules and CSV
- Guest comments
- Replies and editing
- Email and worker
- Separate email configuration
- Отдельная настройка почты
- Styling
- Templates
- Recent comments
- Structured data
- Callbacks
- Object adapters
- Security and privacy
- Deployment
- Performance
- Troubleshooting
- Example and testing
- Release 0.1.0
- Release 0.1.1
- Release 0.2.0
- Stability
- Template contract
- Release 1.0.0
- Release 1.1.0
- Release 1.2.0
- Release 1.3.0
- Security update 1.3.1
- Translated Site roots 1.3.2
- Release 1.4.1
- Выпуск 1.4.1 на русском
- Release 1.4.0
- Выпуск 1.4.0 на русском
- Changelog
- Roadmap
- Support