fix: Fix various bugs with following

This commit is contained in:
Ro 2024-10-10 02:01:30 +00:00
parent 90a158c380
commit 54bc877f0a
6 changed files with 35 additions and 9 deletions

View file

@ -10,6 +10,23 @@ defmodule ActivityPub.Headers do
]
def signing_headers(method, url, body, actor_url, private_key) do
url = case url do
url when is_struct(url, URI) ->
url
url when is_binary(url) ->
URI.parse(url)
end
private_key = case private_key do
"-----BEGIN" <> _ = key_pem ->
key_pem
|> :public_key.pem_decode()
|> hd()
|> :public_key.pem_entry_decode()
private_key ->
private_key
end
method = String.downcase("#{method}")
date = DateTime.utc_now() |> Calendar.strftime(@http_date_format)
host = url.host
@ -35,9 +52,11 @@ defmodule ActivityPub.Headers do
end
def verify(method, path, headers, actor_fetcher \\ &fetch_actor_key/1) do
dbg(headers)
{_key, signature_header} = Enum.find(headers, fn {key, _} -> key == "signature" end)
signature_kv = SignatureSplitter.split(signature_header)
signature_kv = SignatureSplitter.split(signature_header) |> dbg()
key_id = find_value(signature_kv, "keyId")
signature = signature_kv |> find_value("signature") |> Base.decode64!()
signing_text_headers = signature_kv |> find_value("headers") |> String.split(" ")
@ -65,6 +84,7 @@ defmodule ActivityPub.Headers do
value = find_value(header_pairs, header_name)
"#{header_name}: #{value}\n"
end)
|> String.trim()
end
def split_signature_header(signature_header) do
@ -79,6 +99,8 @@ defmodule ActivityPub.Headers do
end
defp find_value(headers, key) do
key = String.downcase(key)
Enum.find_value(headers, fn {key_candidate, value} ->
String.downcase(key_candidate) == key && value
end)
@ -90,7 +112,7 @@ defmodule ActivityPub.Headers do
key_map = body["publicKey"]
if key_map["id"] == key_id do
[public_key | _] =
public_key =
:public_key.pem_decode(key_map["publicKeyPem"])
|> hd()
|> :public_key.pem_entry_decode()

View file

@ -26,6 +26,8 @@ defmodule Postland.Activities do
def cause_effects(%Activity{actor_id: actor_id, type: "Accept", data: %{"object" => %{"type" => "Follow"}}} = activity) do
case Follows.get(Postland.my_actor_id(), actor_id) do
nil ->
# TODO: Need to handle the scenario where the we're following has an alias (/@foobar becomes /users/foobar by the time
# they Accept)
Logger.warning("Got accept for a follow we don't have in the db: #{actor_id}")
{:ok, activity}
@ -50,5 +52,5 @@ defmodule Postland.Activities do
end
end
def cause_effects(activity), do: activity
def cause_effects(activity), do: {:ok, activity}
end

View file

@ -23,7 +23,7 @@ defmodule Postland.Follows do
encoded_followee = Base.url_encode64(to_actor_id)
encoded_follower = Base.url_encode64(Postland.my_actor_id())
actor = ActivityPub.fetch_actor(to_actor_id)
{:ok, actor} = ActivityPub.fetch_actor(to_actor_id)
inbox = Map.get(actor, "inbox")
follow_request = %{
"@context" => "https://www.w3.org/ns/activitystreams",

View file

@ -2,6 +2,8 @@ defmodule PostlandWeb.ActorController do
use PostlandWeb, :controller
def get(conn, _params) do
render(conn, :actor, %{})
conn
|> Plug.Conn.put_resp_header("content-type", "application/activity+json")
|> render(:actor, %{})
end
end

View file

@ -10,13 +10,13 @@ defmodule PostlandWeb.InboxController do
if Headers.verify(conn.method, conn.request_path, conn.req_headers) do
case Activities.process_activity(params) do
{:ok, _activity} ->
render(conn, :ok)
Plug.Conn.send_resp(conn, 200, Jason.encode!(params))
error ->
Logger.error(error)
render(conn, :unprocessable_entity)
Plug.Conn.send_resp(conn, 422, "unprocessable entity")
end
else
render(conn, :forbidden)
Plug.Conn.send_resp(conn, 403, "forbidden")
end
end
end

View file

@ -27,7 +27,7 @@ defmodule PostlandWeb.Router do
get "/.well-known/webfinger", WebfingerController, :get
get "/actor", ActorController, :get
get "/inbox", InboxController, :post
post "/inbox", InboxController, :post
get "/outbox", OutboxController, :get
end