From 6feba31ff3ada0035dd170ac7c6e07ddb0dac98c Mon Sep 17 00:00:00 2001 From: Shadowfacts Date: Mon, 30 Sep 2019 22:23:32 -0400 Subject: [PATCH] Add mix task for adding user --- lib/clacks/activitypub.ex | 26 ++++++++++++++++++++++ lib/clacks/keys.ex | 6 +++++ lib/mix/tasks/clacks/user.ex | 43 ++++++++++++++++++++++++++++++++++++ 3 files changed, 75 insertions(+) create mode 100644 lib/mix/tasks/clacks/user.ex diff --git a/lib/clacks/activitypub.ex b/lib/clacks/activitypub.ex index 16853fb..e667f2c 100644 --- a/lib/clacks/activitypub.ex +++ b/lib/clacks/activitypub.ex @@ -2,6 +2,32 @@ defmodule Clacks.ActivityPub do @context ["https://www.w3.org/ns/activitystreams"] @public "https://www.w3.org/ns/activitystreams#Public" + @spec actor( + id :: String.t(), + username :: String.t(), + display_name :: String.t(), + pem :: String.t() + ) :: map() + def actor(id, username, display_name, pem) do + %{ + "@context" => @context, + "type" => "Person", + "id" => id, + "url" => id, + "preferredUsername" => username, + "name" => display_name, + "followers" => Path.join(id, "followers"), + "following" => Path.join(id, "following"), + "inbox" => Path.join(id, "inbox"), + "outbox" => Path.join(id, "outbox"), + "publicKey" => %{ + "id" => id <> "#main-key", + "owner" => id, + "publicKeyPem" => pem + } + } + end + @spec note( actor :: String.t(), html :: String.t(), diff --git a/lib/clacks/keys.ex b/lib/clacks/keys.ex index 67695cb..3732c7b 100644 --- a/lib/clacks/keys.ex +++ b/lib/clacks/keys.ex @@ -16,4 +16,10 @@ defmodule Clacks.Keys do {:error, error} end end + + def public_key_pem({:RSAPublicKey, _, _} = key) do + entry = :public_key.pem_entry_encode(:SubjectPublicKeyInfo, key) + pem = :public_key.pem_encode([entry]) + {:ok, pem} + end end diff --git a/lib/mix/tasks/clacks/user.ex b/lib/mix/tasks/clacks/user.ex new file mode 100644 index 0000000..d57726b --- /dev/null +++ b/lib/mix/tasks/clacks/user.ex @@ -0,0 +1,43 @@ +defmodule Mix.Tasks.Clacks.User do + use Mix.Task + alias Clacks.{Repo, User, Actor, Keys, ActivityPub} + + @shortdoc "Creates a new user" + def run(["create"]) do + username = IO.gets("Username: ") |> String.trim() + # password = IO.gets("Password: ") |> String.trim() + + {:ok, pem} = Keys.generate_rsa_pem() + {:ok, _private, public} = Keys.keys_from_pem(pem) + {:ok, public_key_pem} = Keys.public_key_pem(public) + + changeset = User.changeset(%User{}, %{username: username, private_key: pem}) + + # start the app so the DB connection is established + Mix.Task.run("app.start") + + {:ok, user} = Repo.insert(changeset) + + url = Application.get_env(:clacks, ClacksWeb.Endpoint)[:url] + + uri = + URI.to_string(%URI{ + scheme: url[:scheme], + host: url[:host], + port: url[:port], + path: Path.join("/users", username) + }) + + actor = + Ecto.build_assoc(user, :actor, %{ + ap_id: uri, + nickname: username, + local: true, + data: ActivityPub.actor(uri, username, username, public_key_pem) + }) + + {:ok, actor} = Repo.insert(actor) + + IO.puts("User #{username} successfully created") + end +end