1.2 KiB · text History 4b6fe3b
defmodule OhMyExOhIrcd.Accounts.Invite do
  @moduledoc """
  Single-use token that lets someone bypass the invite-only gate on
  `/users/register?invite=TOKEN`. Tokens are opaque random strings —
  the URL is the share medium.
  """

  use Ecto.Schema
  import Ecto.Changeset

  alias OhMyExOhIrcd.Accounts.User

  schema "user_invites" do
    field :token, :string
    field :note, :string, default: ""
    field :expires_at, :utc_datetime
    field :consumed_at, :utc_datetime

    belongs_to :created_by, User, foreign_key: :created_by_id
    belongs_to :consumed_by, User, foreign_key: :consumed_by_id

    timestamps(type: :utc_datetime)
  end

  def create_changeset(record, attrs) do
    record
    |> cast(attrs, [:token, :note, :expires_at, :created_by_id])
    |> validate_required([:token])
    |> validate_length(:token, min: 16, max: 64)
    |> unique_constraint(:token)
  end

  def consume_changeset(record, user_id) do
    record
    |> cast(%{consumed_by_id: user_id, consumed_at: DateTime.utc_now(:second)}, [
      :consumed_by_id,
      :consumed_at
    ])
    |> validate_required([:consumed_by_id, :consumed_at])
  end

  def fresh_token do
    :crypto.strong_rand_bytes(24)
    |> Base.url_encode64(padding: false)
  end
end