feat: Add basic actor and webfinger setup

This commit is contained in:
Ro 2024-09-21 19:16:10 -05:00
parent 3b385a6a1c
commit 5529d5f979
8 changed files with 103 additions and 4 deletions

View file

@ -13,11 +13,30 @@ defmodule Postland do
:crypto.strong_rand_bytes(12) |> Base.encode64()
end
def generate_keys(bits \\ 4096) do
{:RSAPrivateKey, _, modulus, publicExponent, _, _, _, _exponent1, _, _, _otherPrimeInfos} =
rsa_private_key = :public_key.generate_key({:rsa, bits, 65537})
rsa_public_key = {:RSAPublicKey, modulus, publicExponent}
pem_entry = :public_key.pem_entry_encode(:RSAPrivateKey, rsa_private_key)
private_key = :public_key.pem_encode([pem_entry])
pem_entry = :public_key.pem_entry_encode(:SubjectPublicKeyInfo, rsa_public_key)
public_key = :public_key.pem_encode([pem_entry])
%{public: public_key, private: private_key}
end
def on_boot_setup() do
if !setup?() do
%{public: public_key, private: private_key} = generate_keys()
attrs = %{
username: "welcome",
password: temporary_password()
password: temporary_password(),
private_key: private_key,
public_key: public_key
}
{:ok, _user} = Accounts.register_user(attrs)

View file

@ -8,6 +8,8 @@ defmodule Postland.Accounts.User do
field :hashed_password, :string, redact: true
field :current_password, :string, virtual: true, redact: true
field :confirmed_at, :utc_datetime
field :private_key, :string
field :public_key, :string
timestamps(type: :utc_datetime)
end
@ -31,7 +33,7 @@ defmodule Postland.Accounts.User do
"""
def registration_changeset(user, attrs, opts \\ []) do
user
|> cast(attrs, [:username, :password])
|> cast(attrs, [:username, :password, :public_key, :private_key])
|> validate_username()
|> validate_password(opts)
end

View file

@ -0,0 +1,7 @@
defmodule PostlandWeb.ActorController do
use PostlandWeb, :controller
def get(conn, _params) do
render(conn, :actor, %{})
end
end

View file

@ -0,0 +1,25 @@
defmodule PostlandWeb.ActorJSON do
use Phoenix.VerifiedRoutes, endpoint: PostlandWeb.Endpoint, router: PostlandWeb.Router
alias Postland.Accounts
def render("actor.json", _assigns) do
user = Accounts.solo_user()
%{
"@context" => [
"https://www.w3.org/ns/activitystreams",
"https://w3id.org/security/v1"
],
"id" => url(~p"/actor"),
"type" => "Person",
"preferredUsername" => user.username,
"inbox" => url(~p"/inbox"),
"publicKey" => %{
"id" => url(~p"/actor#main-key"),
"owner" => url(~p"/actor"),
"publicKeyPem" => user.public_key
}
}
end
end

View file

@ -0,0 +1,9 @@
defmodule PostlandWeb.WebfingerController do
use PostlandWeb, :controller
alias Postland.Accounts
def get(conn, _params) do
render(conn, :webfinger, %{})
end
end

View file

@ -0,0 +1,21 @@
defmodule PostlandWeb.WebfingerJSON do
use Phoenix.VerifiedRoutes, endpoint: PostlandWeb.Endpoint, router: PostlandWeb.Router
alias Postland.Accounts
def render("webfinger.json", _assigns) do
user = Accounts.solo_user()
# TODO: Check that the host here is correct after deploy
%{
subject: "acct:#{user.username}@#{PostlandWeb.Endpoint.host()}",
links: [
%{
"rel" => "self",
"type" => "application/activity+json",
"href" => url(~p"/actor")
}
]
}
end
end

View file

@ -21,6 +21,14 @@ defmodule PostlandWeb.Router do
plug PostlandWeb.Plugs.RedirectIfNotSetup
end
scope "/", PostlandWeb do
pipe_through [:api]
get "/.well-known/webfinger", WebfingerController, :get
get "/actor", ActorController, :get
end
scope "/", PostlandWeb do
pipe_through [:browser, :redirect_if_not_set_up]
@ -55,9 +63,7 @@ defmodule PostlandWeb.Router do
live_session :redirect_if_user_is_authenticated,
on_mount: [{PostlandWeb.UserAuth, :redirect_if_user_is_authenticated}] do
live "/users/register", UserRegistrationLive, :new
live "/users/log_in", UserLoginLive, :new
live "/users/reset_password/:token", UserResetPasswordLive, :edit
end
post "/users/log_in", UserSessionController, :create

View file

@ -0,0 +1,10 @@
defmodule Postland.Repo.Migrations.AddKeysToUser do
use Ecto.Migration
def change do
alter table("users") do
add :private_key, :text, null: false
add :public_key, :text, null: false
end
end
end