# `MishkaCmsCoreWeb.Live.Admin.Components.SecurityCards`
[🔗](https://github.com/mishka-group/mishka_cms_core/blob/v0.0.1/lib/mishka_cms_core_web/live/admin/components/security_cards.ex#L5)

The cards of an account's own sign-in security, drawn on the settings page's Preferences tab: the
core's — its authenticator app (`TwoFactor`) and its recovery codes (`RecoveryCodes`) — and any an
extension adds on the `"account:security:cards"` mishka_installer event, as a widget is added on
`"dashboard:widgets"`.

A card is `%{id: String.t(), priority: integer(), module: module()}`: a LiveComponent drawn with
`id` and `current_user`, low priority first. A plugin is handed `%{cards: cards}` and answers
`{:reply, %{cards: cards}}` with its own added; a core card it drops or redefines comes back as
the core made it. A card that changes what the others show sends `:account_security_changed` to
its LiveView, which redraws every card with `refresh: true` (`refresh/1`).

    use MishkaInstaller.Event.Hook, event: "account:security:cards"

    def call(%{cards: cards} = data),
      do: {:reply, %{data | cards: cards ++ [%{id: "passkeys", priority: 30, module: MyApp.Passkeys}]}}

A card draws itself in `card/1`, with `input_class/0`, `dark_button/0` and `light_button/0`, so
every card on the tab looks alike.

# `card`

```elixir
@type card() :: %{id: String.t(), priority: integer(), module: module()}
```

# `card`

A security card: its title and what it is for, a status chip beside them, and a message —
`{:ok, text}` in green or `{:error, text}` in red — above what the card holds.

## Attributes

* `id` (`:string`) (required)
* `title` (`:string`) (required)
* `description` (`:string`) (required)
* `message` (`:any`) - Defaults to `nil`.
## Slots

* `status`
* `inner_block` (required)

# `chip`

A card's status chip: green and labelled `on` when `on?`, grey and labelled `off` otherwise.
## Attributes

* `id` (`:string`) (required)
* `on?` (`:boolean`) (required)
* `on` (`:string`) (required)
* `off` (`:string`) (required)

# `collect`

```elixir
@spec collect() :: [card()]
```

The cards to draw, the core's first among equals, low priority first.

# `dark_button`

```elixir
@spec dark_button() :: String.t()
```

A card's main button.

# `input_class`

```elixir
@spec input_class() :: String.t()
```

The text field of a card's code form.

# `light_button`

```elixir
@spec light_button() :: String.t()
```

A card's second button.

# `refresh`

```elixir
@spec refresh([card()]) :: :ok
```

Redraws every card in `cards` with `refresh: true`, from the LiveView that holds them.

# `six_digits`

```elixir
@spec six_digits(String.t() | nil) :: {:ok, String.t()} | :error
```

A code typed into a card, as an authenticator app shows it: `{:ok, six_digits}` with spaces
dropped, or `:error` for anything else — answered in the card, never sent, so it spends none of
the account's tries.

---

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