ActivityPub: Make fake Create activities for objects without one.

This commit is contained in:
lain 2018-02-18 11:24:54 +01:00
parent fc9d361d17
commit 77c6c424a6
4 changed files with 40 additions and 4 deletions

View file

@ -273,6 +273,8 @@ def publish(actor, activity) do
end end
end end
# TODO:
# This will create a Create activity, which we need internally at the moment.
def fetch_object_from_id(id) do def fetch_object_from_id(id) do
if object = Object.get_cached_by_ap_id(id) do if object = Object.get_cached_by_ap_id(id) do
{:ok, object} {:ok, object}
@ -280,8 +282,13 @@ def fetch_object_from_id(id) do
with {:ok, %{body: body, status_code: code}} when code in 200..299 <- @httpoison.get(id, [Accept: "application/activity+json"], follow_redirect: true, timeout: 10000, recv_timeout: 20000), with {:ok, %{body: body, status_code: code}} when code in 200..299 <- @httpoison.get(id, [Accept: "application/activity+json"], follow_redirect: true, timeout: 10000, recv_timeout: 20000),
{:ok, data} <- Poison.decode(body), {:ok, data} <- Poison.decode(body),
data <- Transmogrifier.fix_object(data), data <- Transmogrifier.fix_object(data),
%User{} <- User.get_or_fetch_by_ap_id(data["attributedTo"]) do nil <- Object.get_by_ap_id(data["id"]),
Object.create(data) %User{} = user <- User.get_or_fetch_by_ap_id(data["attributedTo"]),
{:ok, activity} = create(%{to: data["to"], actor: user, context: data["context"], object: data, local: false, additional: %{"cc" => data["cc"]}}) do
{:ok, Object.get_by_ap_id(activity.data["object"]["id"])}
else
object = %Object{} -> {:ok, object}
e -> e
end end
end end
end end

View file

@ -4,6 +4,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
""" """
alias Pleroma.User alias Pleroma.User
alias Pleroma.Object alias Pleroma.Object
alias Pleroma.Activity
alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.Web.ActivityPub.ActivityPub
@doc """ @doc """
@ -75,7 +76,7 @@ def handle_incoming(%{"type" => "Like", "object" => object_id, "actor" => actor,
def handle_incoming(%{"type" => "Announce", "object" => object_id, "actor" => actor, "id" => id} = data) do def handle_incoming(%{"type" => "Announce", "object" => object_id, "actor" => actor, "id" => id} = data) do
with %User{} = actor <- User.get_or_fetch_by_ap_id(actor), with %User{} = actor <- User.get_or_fetch_by_ap_id(actor),
{:ok, object} <- ActivityPub.fetch_object_from_id(object_id), {:ok, object} <- get_obj_helper(object_id) || ActivityPub.fetch_object_from_id(object_id),
{:ok, activity, object} <- ActivityPub.announce(actor, object, id, false) do {:ok, activity, object} <- ActivityPub.announce(actor, object, id, false) do
{:ok, activity} {:ok, activity}
else else
@ -89,6 +90,10 @@ def handle_incoming(%{"type" => "Announce", "object" => object_id, "actor" => ac
def handle_incoming(_), do: :error def handle_incoming(_), do: :error
def get_obj_helper(id) do
if object = Object.get_by_ap_id(id), do: {:ok, object}, else: nil
end
@doc @doc
""" """
internal -> Mastodon internal -> Mastodon

View file

@ -266,8 +266,12 @@ test "fetches the latest Follow activity" do
end end
describe "fetching an object" do describe "fetching an object" do
test "it fetches an existing object" do test "it fetches an object" do
{:ok, object} = ActivityPub.fetch_object_from_id("http://mastodon.example.org/@admin/99541947525187367") {:ok, object} = ActivityPub.fetch_object_from_id("http://mastodon.example.org/@admin/99541947525187367")
assert Activity.get_create_activity_by_object_ap_id(object.data["id"])
{:ok, object_again} = ActivityPub.fetch_object_from_id("http://mastodon.example.org/@admin/99541947525187367")
assert object == object_again
end end
end end

View file

@ -72,6 +72,26 @@ test "it works for incoming announces" do
assert data["type"] == "Announce" assert data["type"] == "Announce"
assert data["id"] == "http://mastodon.example.org/users/admin/statuses/99542391527669785/activity" assert data["id"] == "http://mastodon.example.org/users/admin/statuses/99542391527669785/activity"
assert data["object"] == "http://mastodon.example.org/users/admin/statuses/99541947525187367" assert data["object"] == "http://mastodon.example.org/users/admin/statuses/99541947525187367"
assert Activity.get_create_activity_by_object_ap_id(data["object"])
end
test "it works for incoming announces with an existing activity" do
user = insert(:user)
{:ok, activity} = CommonAPI.post(user, %{"status" => "hey"})
data = File.read!("test/fixtures/mastodon-announce.json")
|> Poison.decode!
|> Map.put("object", activity.data["object"]["id"])
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
assert data["actor"] == "http://mastodon.example.org/users/admin"
assert data["type"] == "Announce"
assert data["id"] == "http://mastodon.example.org/users/admin/statuses/99542391527669785/activity"
assert data["object"] == activity.data["object"]["id"]
assert Activity.get_create_activity_by_object_ap_id(data["object"]).id == activity.id
end end
end end