Ithibati.Identity.Grant (Ithibati v0.1.0)

Copy Markdown View Source

The credential half of creating an account, as a fragment the application composes into its own transaction.

The passkey and the recovery codes belong in the same transaction as the account and as whatever the application records about it. Ithibati therefore hands over the pieces rather than running them, and the application appends its own steps:

Ecto.Multi.new()
|> Ecto.Multi.insert(:account, MyApp.Accounts.User.changeset(%User{}, attrs))
|> Ecto.Multi.insert(:membership, fn %{account: account} ->  end)
|> Ithibati.Identity.Grant.with_key_and_codes(key_attrs)
|> MyApp.Repo.transaction()

Summary

Functions

Appends the passkey and the recovery codes to a multi that already creates the account.

Functions

with_key_and_codes(multi, key_attrs, opts \\ [])

Appends the passkey and the recovery codes to a multi that already creates the account.

It adds two steps: :passkey, the credential from Ithibati.Identity.Passkeys.key_attrs/2, and :recovery_codes, whose result is the plaintext batch. The rows hold digests, so this result is the only place the batch exists.

:account names the step that created the account and defaults to :account. :count says how many recovery codes to issue, and 0 issues none. Ithibati replaces the account's existing codes, if it somehow has any, rather than adding to them.

The batch outlives a failed transaction

A later step failing hands you {:error, name, value, changes_so_far}, and changes_so_far still carries the plaintext codes of an account that was rolled back. Do not log that tuple whole. Compose whatever can refuse before this step rather than after it, so a transaction that was never going to commit does not mint a batch on its way to being rolled back. Ithibati.Identity.Instance.claim/2 and Ithibati.Identity.Invitations.accept/3 are both such steps.