# `MishkaCmsCore.Captcha.Widget`
[🔗](https://github.com/mishka-group/mishka_cms_core/blob/v0.0.1/lib/mishka_cms_core/captcha/widget.ex#L5)

`<.captcha>` — the captcha a form asks, drawn where the form puts it. Every runtime template can
call it (`MishkaCmsCore.Runtime.LiveViewHelpers.imports/1`); the sign-in pages put it above their
button:

    <.captcha form={f} for="sign_in" tenant={assigns[:current_tenant]} />

It draws nothing while the scope asks no captcha (`MishkaCmsCore.Captcha.browser/3`). Otherwise it
draws a box the `Captcha` hook (`assets/js/shared_hooks.js`) owns — `phx-update="ignore"`, so no
re-render takes the provider's frame away — holding the hidden input the token goes in, named for
the form's `captcha_token` field. A refused submit is answered with the `"mishka:captcha:reset"`
event, and the hook asks for a fresh check: each token is good once.

## An extension's own form

`for` names the form the way the action checking the token names it. The sign-in pages and the
settings page's test use the strings below; an extension's form passes its own atom, the one its
action hands `MishkaCmsCore.Accounts.CaptchaCheck`:

    prepare &MishkaCmsCore.Accounts.CaptchaCheck.prepare(&1, &2, :newsletter)

    <.captcha form={@form} for={:newsletter} tenant={site_id()} />

## Asked only once the form is sent

A form that wants no check in the visitor's way until they press its button draws none at first.
Its action refuses the first send with `reason: :missing`
(`MishkaCmsCore.Accounts.CaptchaCheck.refusal/1`), and from then on the form draws the check with
`deferred`:

    <.captcha :if={@asked?} form={@form} for={:newsletter} tenant={site_id()} deferred />

`deferred` tells the hook the visitor has already sent the form once: it sends it again by itself
as soon as the check gives a token — when a widget is solved, or at once for a score — so the
visitor presses the button once.

# `captcha`

## Attributes

* `form` (`:any`) (required) - The form the token is sent with.
* `for` (`:any`) (required) - Which form it is, as the action checking it names it: one of "magic_link", "register", "reset_request", "sign_in", "test", or an extension's own form as an atom.
* `tenant` (`:string`) - The site the form signs into; `nil` for a master's. Defaults to `nil`.
* `id` (`:string`) - Defaults to `captcha-<for>`. Defaults to `nil`.
* `deferred` (`:boolean`) - The form has been sent once already: the check sends it again by itself once it gives a token. Defaults to `false`.
* `class` (`:any`) - Defaults to `nil`.

# `form_name`

```elixir
@spec form_name(String.t() | atom()) :: atom()
```

The form `for` names: one of the strings above, or an extension's atom as it is.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
