defmodule Bbox.Voters.Voter do
@doc """
Voter is a election voter.
"""
use Ecto.Schema
import Ecto.Changeset
alias Bbox.Votes.Vote
@primary_key false
@foreign_key_type :string
@derive {Jason.Encoder, except: [:__meta__, :votes]}
schema "voters" do
field(:address, :string)
field(:username, :string)
field(:email, :string)
field(:private_key, :string, virtual: true)
field(:public_key, :string, virtual: true)
has_many(:votes, Vote, foreign_key: :voter_address, references: :address)
timestamps()
end
def changeset(voter, params \\ %{}) do
voter
|> cast(params, [:address, :username, :email, :public_key, :private_key])
|> validate_required([:username, :email])
|> validate_format(:username, ~r/^[a-zA-Z0-9_]{3,20}$/, message: "invalid username")
|> validate_format(:email, ~r/^\S+@\S+\.\S+$/, message: "invalid email")
|> put_params()
end
defp put_params(%Ecto.Changeset{valid?: true} = changeset) do
private_key = X509.PrivateKey.new_rsa(2048)
public_key =
private_key
|> X509.PublicKey.derive()
|> X509.PublicKey.to_pem()
|> Base.encode32()
private_key =
private_key
|> X509.PrivateKey.to_pem()
|> Base.encode32()
address = String.slice(public_key, 0..20)
changeset
|> put_change(:public_key, public_key)
|> put_change(:private_key, private_key)
|> put_change(:address, address)
end
defp put_params(changeset), do: changeset
end