aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/pleroma/user.ex29
-rw-r--r--lib/pleroma/web/activity_pub/activity_pub.ex44
-rw-r--r--lib/pleroma/web/activity_pub/activity_pub_controller.ex2
-rw-r--r--lib/pleroma/web/federator/federator.ex3
-rw-r--r--lib/pleroma/web/http_signatures/http_signatures.ex30
5 files changed, 92 insertions, 16 deletions
diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex
index 47aefaeba..ddf66cee9 100644
--- a/lib/pleroma/user.ex
+++ b/lib/pleroma/user.ex
@@ -383,10 +383,33 @@ defmodule Pleroma.User do
:ok
end
+ def get_or_fetch_by_ap_id(ap_id) do
+ if user = get_by_ap_id(ap_id) do
+ user
+ else
+ with {:ok, user} <- ActivityPub.make_user_from_ap_id(ap_id) do
+ user
+ end
+ end
+ end
+
+ # AP style
+ def public_key_from_info(%{"source_data" => %{"publicKey" => %{"publicKeyPem" => public_key_pem}}}) do
+ key = :public_key.pem_decode(public_key_pem)
+ |> hd()
+ |> :public_key.pem_entry_decode()
+
+ {:ok, key}
+ end
+
+ # OStatus Magic Key
+ def public_key_from_info(%{"magic_key" => magic_key}) do
+ {:ok, Pleroma.Web.Salmon.decode_key(magic_key)}
+ end
+
def get_public_key_for_ap_id(ap_id) do
- with %User{} = user <- get_cached_by_ap_id(ap_id),
- %{info: %{"magic_key" => magic_key}} <- user,
- public_key <- Pleroma.Web.Salmon.decode_key(magic_key) do
+ with %User{} = user <- get_or_fetch_by_ap_id(ap_id),
+ {:ok, public_key} <- public_key_from_info(user.info) do
{:ok, public_key}
else
_ -> :error
diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex
index 4d0de71e4..6e29768d1 100644
--- a/lib/pleroma/web/activity_pub/activity_pub.ex
+++ b/lib/pleroma/web/activity_pub/activity_pub.ex
@@ -223,18 +223,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
Repo.insert(%Object{data: data})
end
- def prepare_incoming(%{"type" => "Create", "object" => %{"type" => "Note"} = object} = data) do
- with {:ok, user} <- OStatus.find_or_make_user(data["actor"]) do
- data
- else
- _e -> :error
- end
- end
-
- def prepare_incoming(_) do
- :error
- end
-
def make_user_from_ap_id(ap_id) do
with {:ok, %{status_code: 200, body: body}} <- @httpoison.get(ap_id, ["Accept": "application/activity+json"]),
{:ok, data} <- Poison.decode(body)
@@ -252,4 +240,36 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
User.insert_or_update_user(user_data)
end
end
+
+ # TODO: Extract to own module, align as close to Mastodon format as possible.
+ def sanitize_outgoing_activity_data(data) do
+ data
+ |> Map.put("@context", "https://www.w3.org/ns/activitystreams")
+ end
+
+ def prepare_incoming(%{"type" => "Create", "object" => %{"type" => "Note"} = object} = data) do
+ with {:ok, user} <- OStatus.find_or_make_user(data["actor"]) do
+ {:ok, data}
+ else
+ _e -> :error
+ end
+ end
+
+ def prepare_incoming(_) do
+ :error
+ end
+
+ def publish(actor, activity) do
+ remote_users = Pleroma.Web.Salmon.remote_users(activity)
+ data = sanitize_outgoing_activity_data(activity.data)
+ Enum.each remote_users, fn(user) ->
+ if user.info["ap_enabled"] do
+ inbox = user.info["source_data"]["inbox"]
+ Logger.info("Federating #{activity.data["id"]} to #{inbox}")
+ host = URI.parse(inbox).host
+ signature = Pleroma.Web.HTTPSignatures.sign(actor, %{host: host})
+ @httpoison.post(inbox, Poison.encode!(data), [{"Content-Type", "application/activity+json"}, {"signature", signature}])
+ end
+ end
+ end
end
diff --git a/lib/pleroma/web/activity_pub/activity_pub_controller.ex b/lib/pleroma/web/activity_pub/activity_pub_controller.ex
index 0d3e8f44c..35723f75c 100644
--- a/lib/pleroma/web/activity_pub/activity_pub_controller.ex
+++ b/lib/pleroma/web/activity_pub/activity_pub_controller.ex
@@ -23,6 +23,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
with {:ok, data} <- ActivityPub.prepare_incoming(params),
{:ok, activity} <- ActivityPub.insert(data, false) do
json(conn, "ok")
+ else
+ e -> IO.inspect(e)
end
end
end
diff --git a/lib/pleroma/web/federator/federator.ex b/lib/pleroma/web/federator/federator.ex
index c9f9dc7a1..68e5544e7 100644
--- a/lib/pleroma/web/federator/federator.ex
+++ b/lib/pleroma/web/federator/federator.ex
@@ -47,6 +47,9 @@ defmodule Pleroma.Web.Federator do
Logger.debug(fn -> "Sending #{activity.data["id"]} out via websub" end)
Websub.publish(Pleroma.Web.OStatus.feed_path(actor), actor, activity)
+
+ Logger.debug(fn -> "Sending #{activity.data["id"]} out via AP" end)
+ Pleroma.Web.ActivityPub.ActivityPub.publish(actor, activity)
end
end
diff --git a/lib/pleroma/web/http_signatures/http_signatures.ex b/lib/pleroma/web/http_signatures/http_signatures.ex
index 830ddf64d..cdc5e1f3f 100644
--- a/lib/pleroma/web/http_signatures/http_signatures.ex
+++ b/lib/pleroma/web/http_signatures/http_signatures.ex
@@ -1,6 +1,7 @@
# https://tools.ietf.org/html/draft-cavage-http-signatures-08
defmodule Pleroma.Web.HTTPSignatures do
alias Pleroma.User
+ alias Pleroma.Web.ActivityPub.ActivityPub
def split_signature(sig) do
default = %{"headers" => "date"}
@@ -28,7 +29,16 @@ defmodule Pleroma.Web.HTTPSignatures do
# For now, fetch the key for the actor.
with actor_id <- conn.params["actor"],
{:ok, public_key} <- User.get_public_key_for_ap_id(actor_id) do
- validate_conn(conn, public_key)
+ if validate_conn(conn, public_key) do
+ true
+ else
+ # Fetch user anew and try one more time
+ with actor_id <- conn.params["actor"],
+ {:ok, _user} <- ActivityPub.make_user_from_ap_id(actor_id),
+ {:ok, public_key} <- User.get_public_key_for_ap_id(actor_id) do
+ validate_conn(conn, public_key)
+ end
+ end
else
_ -> false
end
@@ -45,4 +55,22 @@ defmodule Pleroma.Web.HTTPSignatures do
|> Enum.map(fn (header) -> "#{header}: #{headers[header]}" end)
|> Enum.join("\n")
end
+
+ def sign(user, headers) do
+ with {:ok, %{info: %{"keys" => keys}}} <- Pleroma.Web.WebFinger.ensure_keys_present(user),
+ {:ok, private_key, _} = Pleroma.Web.Salmon.keys_from_pem(keys) do
+ sigstring = build_signing_string(headers, Map.keys(headers))
+ signature = :public_key.sign(sigstring, :sha256, private_key)
+ |> Base.encode64()
+
+ [
+ keyId: user.ap_id <> "#main-key",
+ algorithm: "rsa-sha256",
+ headers: Map.keys(headers) |> Enum.join(" "),
+ signature: signature
+ ]
+ |> Enum.map(fn({k, v}) -> "#{k}=\"#{v}\"" end)
+ |> Enum.join(",")
+ end
+ end
end