48 lines
1.4 KiB
Elixir
48 lines
1.4 KiB
Elixir
defmodule RecycledCloud.Accounts.Key do
|
|
use Ecto.Schema
|
|
import Ecto.Changeset
|
|
|
|
schema "keys" do
|
|
field :comment, :string
|
|
field :value, :string
|
|
field :fingerprint, :string
|
|
belongs_to :user, RecycledCloud.Accounts.User
|
|
|
|
timestamps()
|
|
end
|
|
|
|
def process_ssh_key(changeset, value_field, fingerprint_field, comment_field) do
|
|
raw_value = get_field(changeset, value_field)
|
|
comment = get_field(changeset, comment_field)
|
|
|
|
with {:is_valid, true} <- {:is_valid, changeset.valid?},
|
|
[{pk, attrs}] <- :public_key.ssh_decode(raw_value, :public_key) do
|
|
|
|
fingerprint = :public_key.ssh_hostkey_fingerprint(pk) |> List.to_string
|
|
changeset = put_change(changeset, fingerprint_field, fingerprint)
|
|
|
|
# Fetch comment from key, if not provided.
|
|
embedded_comment = attrs
|
|
|> Enum.into(%{})
|
|
|> Map.get(:comment)
|
|
|
|
case {comment, embedded_comment} do
|
|
{nil, nil} -> changeset
|
|
{nil, new_comment} ->
|
|
put_change(changeset, comment_field, List.to_string(new_comment))
|
|
{_, _} -> changeset
|
|
end
|
|
else
|
|
{:is_valid, false} -> changeset
|
|
_ -> add_error(changeset, value_field, "key is invalid")
|
|
end
|
|
end
|
|
|
|
@doc false
|
|
def changeset(key, attrs) do
|
|
key
|
|
|> cast(attrs, [:comment, :value])
|
|
|> validate_required([:value])
|
|
|> process_ssh_key(:value, :fingerprint, :comment)
|
|
end
|
|
end
|