aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/pleroma/web/activity_pub/activity_pub.ex5
-rw-r--r--lib/pleroma/web/activity_pub/activity_pub_controller.ex24
-rw-r--r--lib/pleroma/web/activity_pub/transmogrifier.ex135
-rw-r--r--test/fixtures/httpoison_mock/http___mastodon.example.org_users_admin_status_1234.json55
-rw-r--r--test/fixtures/kroeg-announce-with-inline-actor.json1
-rw-r--r--test/fixtures/kroeg-array-less-emoji.json1
-rw-r--r--test/fixtures/kroeg-array-less-hashtag.json1
-rw-r--r--test/support/httpoison_mock.ex11
-rw-r--r--test/web/activity_pub/transmogrifier_test.exs24
9 files changed, 203 insertions, 54 deletions
diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex
index 361e93e91..e03e7c471 100644
--- a/lib/pleroma/web/activity_pub/activity_pub.ex
+++ b/lib/pleroma/web/activity_pub/activity_pub.ex
@@ -683,7 +683,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
(Pleroma.Web.Salmon.remote_users(activity) ++ followers)
|> Enum.filter(fn user -> User.ap_enabled?(user) end)
|> Enum.map(fn %{info: %{"source_data" => data}} ->
- (data["endpoints"] && data["endpoints"]["sharedInbox"]) || data["inbox"]
+ (is_map(data["endpoints"]) && Map.get(data["endpoints"], "sharedInbox")) || data["inbox"]
end)
|> Enum.uniq()
|> Enum.filter(fn inbox -> should_federate?(inbox, public) end)
@@ -756,6 +756,9 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
{:ok, activity} <- Transmogrifier.handle_incoming(params) do
{:ok, Object.normalize(activity.data["object"])}
else
+ {:reject, nil} ->
+ {:reject, nil}
+
object = %Object{} ->
{:ok, object}
diff --git a/lib/pleroma/web/activity_pub/activity_pub_controller.ex b/lib/pleroma/web/activity_pub/activity_pub_controller.ex
index 52b2a467e..2750add8b 100644
--- a/lib/pleroma/web/activity_pub/activity_pub_controller.ex
+++ b/lib/pleroma/web/activity_pub/activity_pub_controller.ex
@@ -93,19 +93,29 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do
json(conn, "ok")
end
+ # only accept relayed Creates
+ def inbox(conn, %{"type" => "Create"} = params) do
+ Logger.info(
+ "Signature missing or not from author, relayed Create message, fetching object from source"
+ )
+
+ ActivityPub.fetch_object_from_id(params["object"]["id"])
+
+ json(conn, "ok")
+ end
+
def inbox(conn, params) do
headers = Enum.into(conn.req_headers, %{})
- if !String.contains?(headers["signature"] || "", params["actor"]) do
- Logger.info("Signature not from author, relayed message, fetching from source")
- ActivityPub.fetch_object_from_id(params["object"]["id"])
- else
- Logger.info("Signature error - make sure you are forwarding the HTTP Host header!")
- Logger.info("Could not validate #{params["actor"]}")
+ if String.contains?(headers["signature"], params["actor"]) do
+ Logger.info(
+ "Signature validation error for: #{params["actor"]}, make sure you are forwarding the HTTP Host header!"
+ )
+
Logger.info(inspect(conn.req_headers))
end
- json(conn, "ok")
+ json(conn, "error")
end
def relay(conn, params) do
diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex
index 48c3aec97..aece77a54 100644
--- a/lib/pleroma/web/activity_pub/transmogrifier.ex
+++ b/lib/pleroma/web/activity_pub/transmogrifier.ex
@@ -21,13 +21,17 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
if is_binary(Enum.at(actor, 0)) do
Enum.at(actor, 0)
else
- Enum.find(actor, fn %{"type" => type} -> type == "Person" end)
+ Enum.find(actor, fn %{"type" => type} -> type in ["Person", "Service", "Application"] end)
|> Map.get("id")
end
end
- def get_actor(%{"actor" => actor}) when is_map(actor) do
- actor["id"]
+ def get_actor(%{"actor" => %{"id" => id}}) when is_bitstring(id) do
+ id
+ end
+
+ def get_actor(%{"actor" => nil, "attributedTo" => actor}) when not is_nil(actor) do
+ get_actor(%{"actor" => actor})
end
@doc """
@@ -96,9 +100,25 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
object
end
- def fix_in_reply_to(%{"inReplyTo" => in_reply_to_id} = object)
- when not is_nil(in_reply_to_id) do
- case ActivityPub.fetch_object_from_id(in_reply_to_id) do
+ def fix_in_reply_to(%{"inReplyTo" => in_reply_to} = object)
+ when not is_nil(in_reply_to) do
+ in_reply_to_id =
+ cond do
+ is_bitstring(in_reply_to) ->
+ in_reply_to
+
+ is_map(in_reply_to) && is_bitstring(in_reply_to["id"]) ->
+ in_reply_to["id"]
+
+ is_list(in_reply_to) && is_bitstring(Enum.at(in_reply_to, 0)) ->
+ Enum.at(in_reply_to, 0)
+
+ # Maybe I should output an error too?
+ true ->
+ ""
+ end
+
+ case fetch_obj_helper(in_reply_to_id) do
{:ok, replied_object} ->
with %Activity{} = activity <-
Activity.get_create_activity_by_object_ap_id(replied_object.data["id"]) do
@@ -110,12 +130,12 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|> Map.put("context", replied_object.data["context"] || object["conversation"])
else
e ->
- Logger.error("Couldn't fetch #{object["inReplyTo"]} #{inspect(e)}")
+ Logger.error("Couldn't fetch \"#{inspect(in_reply_to_id)}\", error: #{inspect(e)}")
object
end
e ->
- Logger.error("Couldn't fetch #{object["inReplyTo"]} #{inspect(e)}")
+ Logger.error("Couldn't fetch \"#{inspect(in_reply_to_id)}\", error: #{inspect(e)}")
object
end
end
@@ -130,9 +150,9 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|> Map.put("conversation", context)
end
- def fix_attachments(object) do
+ def fix_attachments(%{"attachment" => attachment} = object) when is_list(attachment) do
attachments =
- (object["attachment"] || [])
+ attachment
|> Enum.map(fn data ->
url = [%{"type" => "Link", "mediaType" => data["mediaType"], "href" => data["url"]}]
Map.put(data, "url", url)
@@ -142,21 +162,20 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|> Map.put("attachment", attachments)
end
- def fix_emoji(object) do
- tags = object["tag"] || []
+ def fix_attachments(%{"attachment" => attachment} = object) when is_map(attachment) do
+ Map.put(object, "attachment", [attachment])
+ |> fix_attachments()
+ end
+
+ def fix_attachments(object), do: object
+
+ def fix_emoji(%{"tag" => tags} = object) when is_list(tags) do
emoji = tags |> Enum.filter(fn data -> data["type"] == "Emoji" and data["icon"] end)
emoji =
emoji
|> Enum.reduce(%{}, fn data, mapping ->
- name = data["name"]
-
- name =
- if String.starts_with?(name, ":") do
- name |> String.slice(1..-2)
- else
- name
- end
+ name = String.trim(data["name"], ":")
mapping |> Map.put(name, data["icon"]["url"])
end)
@@ -168,18 +187,37 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
|> Map.put("emoji", emoji)
end
- def fix_tag(object) do
+ def fix_emoji(%{"tag" => %{"type" => "Emoji"} = tag} = object) do
+ name = String.trim(tag["name"], ":")
+ emoji = %{name => tag["icon"]["url"]}
+
+ object
+ |> Map.put("emoji", emoji)
+ end
+
+ def fix_emoji(object), do: object
+
+ def fix_tag(%{"tag" => tag} = object) when is_list(tag) do
tags =
- (object["tag"] || [])
+ tag
|> Enum.filter(fn data -> data["type"] == "Hashtag" and data["name"] end)
|> Enum.map(fn data -> String.slice(data["name"], 1..-1) end)
- combined = (object["tag"] || []) ++ tags
+ combined = tag ++ tags
object
|> Map.put("tag", combined)
end
+ def fix_tag(%{"tag" => %{"type" => "Hashtag", "name" => hashtag} = tag} = object) do
+ combined = [tag, String.slice(hashtag, 1..-1)]
+
+ object
+ |> Map.put("tag", combined)
+ end
+
+ def fix_tag(object), do: object
+
# content map usually only has one language so this will do for now.
def fix_content_map(%{"contentMap" => content_map} = object) do
content_groups = Map.to_list(content_map)
@@ -285,7 +323,8 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
def handle_incoming(
%{"type" => "Accept", "object" => follow_object, "actor" => actor, "id" => id} = data
) do
- with %User{} = followed <- User.get_or_fetch_by_ap_id(actor),
+ with actor <- get_actor(data),
+ %User{} = followed <- User.get_or_fetch_by_ap_id(actor),
{:ok, follow_activity} <- get_follow_activity(follow_object, followed),
%User{local: true} = follower <- User.get_cached_by_ap_id(follow_activity.data["actor"]),
{:ok, activity} <-
@@ -309,7 +348,8 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
def handle_incoming(
%{"type" => "Reject", "object" => follow_object, "actor" => actor, "id" => id} = data
) do
- with %User{} = followed <- User.get_or_fetch_by_ap_id(actor),
+ with actor <- get_actor(data),
+ %User{} = followed <- User.get_or_fetch_by_ap_id(actor),
{:ok, follow_activity} <- get_follow_activity(follow_object, followed),
%User{local: true} = follower <- User.get_cached_by_ap_id(follow_activity.data["actor"]),
{:ok, activity} <-
@@ -329,11 +369,11 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
end
def handle_incoming(
- %{"type" => "Like", "object" => object_id, "actor" => actor, "id" => id} = _data
+ %{"type" => "Like", "object" => object_id, "actor" => actor, "id" => id} = data
) do
- with %User{} = actor <- User.get_or_fetch_by_ap_id(actor),
- {:ok, object} <-
- get_obj_helper(object_id) || ActivityPub.fetch_object_from_id(object_id),
+ with actor <- get_actor(data),
+ %User{} = actor <- User.get_or_fetch_by_ap_id(actor),
+ {:ok, object} <- get_obj_helper(object_id) || fetch_obj_helper(object_id),
{:ok, activity, _object} <- ActivityPub.like(actor, object, id, false) do
{:ok, activity}
else
@@ -342,11 +382,11 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
end
def handle_incoming(
- %{"type" => "Announce", "object" => object_id, "actor" => actor, "id" => id} = _data
+ %{"type" => "Announce", "object" => object_id, "actor" => actor, "id" => id} = data
) do
- with %User{} = actor <- User.get_or_fetch_by_ap_id(actor),
- {:ok, object} <-
- get_obj_helper(object_id) || ActivityPub.fetch_object_from_id(object_id),
+ with actor <- get_actor(data),
+ %User{} = actor <- User.get_or_fetch_by_ap_id(actor),
+ {:ok, object} <- get_obj_helper(object_id) || fetch_obj_helper(object_id),
{:ok, activity, _object} <- ActivityPub.announce(actor, object, id, false) do
{:ok, activity}
else
@@ -390,13 +430,13 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
# TODO: Make secure.
def handle_incoming(
- %{"type" => "Delete", "object" => object_id, "actor" => actor, "id" => _id} = _data
+ %{"type" => "Delete", "object" => object_id, "actor" => actor, "id" => _id} = data
) do
object_id = Utils.get_ap_id(object_id)
- with %User{} = _actor <- User.get_or_fetch_by_ap_id(actor),
- {:ok, object} <-
- get_obj_helper(object_id) || ActivityPub.fetch_object_from_id(object_id),
+ with actor <- get_actor(data),
+ %User{} = _actor <- User.get_or_fetch_by_ap_id(actor),
+ {:ok, object} <- get_obj_helper(object_id) || fetch_obj_helper(object_id),
{:ok, activity} <- ActivityPub.delete(object, false) do
{:ok, activity}
else
@@ -410,11 +450,11 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
"object" => %{"type" => "Announce", "object" => object_id},
"actor" => actor,
"id" => id
- } = _data
+ } = data
) do
- with %User{} = actor <- User.get_or_fetch_by_ap_id(actor),
- {:ok, object} <-
- get_obj_helper(object_id) || ActivityPub.fetch_object_from_id(object_id),
+ with actor <- get_actor(data),
+ %User{} = actor <- User.get_or_fetch_by_ap_id(actor),
+ {:ok, object} <- get_obj_helper(object_id) || fetch_obj_helper(object_id),
{:ok, activity, _} <- ActivityPub.unannounce(actor, object, id, false) do
{:ok, activity}
else
@@ -483,11 +523,11 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
"object" => %{"type" => "Like", "object" => object_id},
"actor" => actor,
"id" => id
- } = _data
+ } = data
) do
- with %User{} = actor <- User.get_or_fetch_by_ap_id(actor),
- {:ok, object} <-
- get_obj_helper(object_id) || ActivityPub.fetch_object_from_id(object_id),
+ with actor <- get_actor(data),
+ %User{} = actor <- User.get_or_fetch_by_ap_id(actor),
+ {:ok, object} <- get_obj_helper(object_id) || fetch_obj_helper(object_id),
{:ok, activity, _, _} <- ActivityPub.unlike(actor, object, id, false) do
{:ok, activity}
else
@@ -497,6 +537,9 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
def handle_incoming(_), do: :error
+ def fetch_obj_helper(id) when is_bitstring(id), do: ActivityPub.fetch_object_from_id(id)
+ def fetch_obj_helper(obj) when is_map(obj), do: ActivityPub.fetch_object_from_id(obj["id"])
+
def get_obj_helper(id) do
if object = Object.normalize(id), do: {:ok, object}, else: nil
end
@@ -592,7 +635,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
def maybe_fix_object_url(data) do
if is_binary(data["object"]) and not String.starts_with?(data["object"], "http") do
- case ActivityPub.fetch_object_from_id(data["object"]) do
+ case fetch_obj_helper(data["object"]) do
{:ok, relative_object} ->
if relative_object.data["external_url"] do
_data =
diff --git a/test/fixtures/httpoison_mock/http___mastodon.example.org_users_admin_status_1234.json b/test/fixtures/httpoison_mock/http___mastodon.example.org_users_admin_status_1234.json
new file mode 100644
index 000000000..5c7c9c6d3
--- /dev/null
+++ b/test/fixtures/httpoison_mock/http___mastodon.example.org_users_admin_status_1234.json
@@ -0,0 +1,55 @@
+{
+ "@context": [
+ "https://www.w3.org/ns/activitystreams",
+ "https://w3id.org/security/v1",
+ {
+ "manuallyApprovesFollowers": "as:manuallyApprovesFollowers",
+ "sensitive": "as:sensitive",
+ "movedTo": {
+ "@id": "as:movedTo",
+ "@type": "@id"
+ },
+ "Hashtag": "as:Hashtag",
+ "ostatus": "http://ostatus.org#",
+ "atomUri": "ostatus:atomUri",
+ "inReplyToAtomUri": "ostatus:inReplyToAtomUri",
+ "conversation": "ostatus:conversation",
+ "toot": "http://joinmastodon.org/ns#",
+ "Emoji": "toot:Emoji",
+ "focalPoint": {
+ "@container": "@list",
+ "@id": "toot:focalPoint"
+ },
+ "featured": {
+ "@id": "toot:featured",
+ "@type": "@id"
+ },
+ "schema": "http://schema.org#",
+ "PropertyValue": "schema:PropertyValue",
+ "value": "schema:value"
+ }
+ ],
+ "id": "http://mastodon.example.org/users/admin/statuses/100787282858396771",
+ "type": "Note",
+ "summary": null,
+ "inReplyTo": null,
+ "published": "2018-09-25T16:11:29Z",
+ "url": "https://mastodon.example.org/@admin/100787282858396771",
+ "attributedTo": "http://mastodon.example.org/users/admin",
+ "to": [
+ "https://www.w3.org/ns/activitystreams#Public"
+ ],
+ "cc": [
+ "http://mastodon.example.org/users/admin/followers"
+ ],
+ "sensitive": false,
+ "atomUri": "http://mastodon.example.org/users/admin/statuses/100787282858396771",
+ "inReplyToAtomUri": null,
+ "conversation": "tag:mastodon.social,2018-09-25:objectId=55659382:objectType=Conversation",
+ "content": "<p>the name&apos;s jond (jeans bond)</p>",
+ "contentMap": {
+ "en": "<p>the name&apos;s jond (jeans bond)</p>"
+ },
+ "attachment": [],
+ "tag": []
+}
diff --git a/test/fixtures/kroeg-announce-with-inline-actor.json b/test/fixtures/kroeg-announce-with-inline-actor.json
new file mode 100644
index 000000000..7bd6e8199
--- /dev/null
+++ b/test/fixtures/kroeg-announce-with-inline-actor.json
@@ -0,0 +1 @@
+{"@context":["https://www.w3.org/ns/activitystreams","https://puckipedia.com/-/context"],"actor":{"endpoints":"https://puckipedia.com/#endpoints","followers":"https://puckipedia.com/followers","following":"https://puckipedia.com/following","icon":{"mediaType":"image/png","type":"Image","url":"https://puckipedia.com/images/avatar.png"},"id":"https://puckipedia.com/","inbox":"https://puckipedia.com/inbox","kroeg:blocks":{"id":"https://puckipedia.com/blocks"},"liked":"https://puckipedia.com/liked","manuallyApprovesFollowers":false,"name":"HACKER TEEN PUCKIPEDIA 👩‍💻","outbox":"https://puckipedia.com/outbox","preferredUsername":"puckipedia","publicKey":{"id":"https://puckipedia.com/#key","owner":"https://puckipedia.com/","publicKeyPem":"-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvN05xIcFE0Qgany7Rht4\n0ZI5wu++IT7K5iSqRimBYkpoeHbVcT9RFlW+aWH/QJJW/YgZ7+LMr8AMCrKrwSpS\nCndyrpx4O4lZ3FNRLu7tbklh01rGZfE6R1SFfYBpvMvImc9nYT6iezYDbv6NkHku\no3aVhjql216XlA0OhIrqQme9sAdrLbjbMrTUS8douCTkDOX+JFj1ghHCqdYEMZJI\nOY9kovtgnqyxFLm0RsPGsO1+g/OVojqG+VqHz6O2lceaTVQLlnZ4gOhLVG1tVsA2\nRfXQK+R/VgXncYE+BlQVd/tcdGAz7CDL7PP3rP65gmARnafhGR96cCOi/KzlAXSO\nMwIDAQAB\n-----END PUBLIC KEY-----","type":[]},"summary":"<p>federated hacker teen<br/>\n[<a href=\"https://pronoun.is/she\">she</a>/<a href=\"https://pronoun.is/they\">they</a>]</p>","type":"Person","updated":"2017-12-19T16:56:29.7576707+00:00"},"cc":"http://mastodon.example.org/users/admin","id":"https://puckipedia.com/cc56a9658e","object":{"as:sensitive":false,"attributedTo":{"endpoints":{"sharedInbox":"https://mastodon.social/inbox","type":[]},"followers":"http://mastodon.example.org/users/admin/followers","following":"http://mastodon.example.org/users/admin/following","icon":{"mediaType":"image/png","type":"Image","url":"https://files.mastodon.social/accounts/avatars/000/015/163/original/70ca6c52b01ca913.png"},"id":"http://mastodon.example.org/users/admin","inbox":"http://mastodon.example.org/users/admin/inbox","manuallyApprovesFollowers":{"@value":"False","type":"xsd:boolean"},"name":"","outbox":"http://mastodon.example.org/users/admin/outbox","preferredUsername":"revenant","publicKey":{"id":"http://mastodon.example.org/users/admin#main-key","owner":"http://mastodon.example.org/users/admin","publicKeyPem":"-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0gEN3wPW7gkE2gQqnmfB\n1ychjmFIf2LIwY0oCJLiGE/xpZrUKoq+eWH30AP7mATw4LD0gOYABL/ijqPUrPqR\nDXLL+0CqMP8HsZKvRlj9KArMK3YtNiSGGj2U7iReiRrD7nJzjJlsjjJXflLZhZ7/\nenSv1CcaeK8tB0PoAgShy/MyfhPF7WI5/Zm9DmmDQFvUEnDYKXAf/vG/IWw1EyMC\nkbaEYJeIowQU3GsbPxzRGI22bQtfotm431Ch2MbNo+kyzmYVFLAVoSGNMzvJwOPg\nTxLIIBeQXG7MinRyK887yPKhxhcALea4yCcALaa+3jPE7yqwIKYwTHtSlblsHDAo\nmQIDAQAB\n-----END PUBLIC KEY-----\n","type":[]},"summary":"<p>neatly partitioned meats and cheeses appeal to me on an aesthetic level | any pronouns | revenant1.net</p>","type":"Person","url":"https://mastodon.social/@revenant"},"cc":"http://mastodon.example.org/users/admin/followers","content":"<p>the name&apos;s jond (jeans bond)</p>","contentMap":{"en":"<p>the name&apos;s jond (jeans bond)</p>"},"conversation":"tag:mastodon.social,2018-09-25:objectId=55659382:objectType=Conversation","id":"http://mastodon.example.org/users/admin/statuses/100787282858396771","ostatus:atomUri":"http://mastodon.example.org/users/admin/statuses/100787282858396771","published":"2018-09-25T16:11:29Z","to":"https://www.w3.org/ns/activitystreams#Public","type":"Note","url":"https://mastodon.social/@revenant/100787282858396771"},"to":["https://www.w3.org/ns/activitystreams#Public","https://puckipedia.com/followers"],"type":"Announce"}
diff --git a/test/fixtures/kroeg-array-less-emoji.json b/test/fixtures/kroeg-array-less-emoji.json
new file mode 100644
index 000000000..3d7025f55
--- /dev/null
+++ b/test/fixtures/kroeg-array-less-emoji.json
@@ -0,0 +1 @@
+{"@context":["https://www.w3.org/ns/activitystreams","https://puckipedia.com/-/context"],"actor":{"endpoints":"https://puckipedia.com/#endpoints","followers":"https://puckipedia.com/followers","following":"https://puckipedia.com/following","icon":{"mediaType":"image/png","type":"Image","url":"https://puckipedia.com/images/avatar.png"},"id":"https://puckipedia.com/","inbox":"https://puckipedia.com/inbox","kroeg:blocks":{"id":"https://puckipedia.com/blocks"},"liked":"https://puckipedia.com/liked","manuallyApprovesFollowers":false,"name":"HACKER TEEN PUCKIPEDIA 👩‍💻","outbox":"https://puckipedia.com/outbox","preferredUsername":"puckipedia","publicKey":{"id":"https://puckipedia.com/#key","owner":"https://puckipedia.com/","publicKeyPem":"-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvN05xIcFE0Qgany7Rht4\n0ZI5wu++IT7K5iSqRimBYkpoeHbVcT9RFlW+aWH/QJJW/YgZ7+LMr8AMCrKrwSpS\nCndyrpx4O4lZ3FNRLu7tbklh01rGZfE6R1SFfYBpvMvImc9nYT6iezYDbv6NkHku\no3aVhjql216XlA0OhIrqQme9sAdrLbjbMrTUS8douCTkDOX+JFj1ghHCqdYEMZJI\nOY9kovtgnqyxFLm0RsPGsO1+g/OVojqG+VqHz6O2lceaTVQLlnZ4gOhLVG1tVsA2\nRfXQK+R/VgXncYE+BlQVd/tcdGAz7CDL7PP3rP65gmARnafhGR96cCOi/KzlAXSO\nMwIDAQAB\n-----END PUBLIC KEY-----","type":[]},"summary":"<p>federated hacker teen<br/>\n[<a href=\"https://pronoun.is/she\">she</a>/<a href=\"https://pronoun.is/they\">they</a>]</p>","type":"Person","updated":"2017-12-19T16:56:29.7576707+00:00"},"cc":"https://puckipedia.com/followers","id":"https://puckipedia.com/1jjx-ob5r","object":{"attributedTo":"https://puckipedia.com/","cc":"https://puckipedia.com/followers","content":"<p>spinning up an extra process that just handles the delivery queue to see what happens. The concept of this working is kind of amusing :icon_e_smile: </p><p>I should probably add back some code to synchronize state between multiple processes; and add back the pubsub mechanism so live streams of collections can return! Also I should add database transactions back.</p>","conversation":"https://puckipedia.com/f/conversation/4eae6d6c-d046-4737-9c17-c7a791c7ad77","id":"https://puckipedia.com/1jjx-ob5r/note","likes":"https://puckipedia.com/1jjx-ob5r/note/likes","name":"Kroeg dev thread","published":"2018-09-25T22:35:59.770Z","replies":"https://puckipedia.com/1jjx-ob5r/note/replies","shares":"https://puckipedia.com/1jjx-ob5r/note/shares","tag":{"icon":{"mediaType":"image/png","type":"Image","url":"https://puckipedia.com/forum/images/smilies/icon_e_smile.png"},"id":"https://puckipedia.com/forum/images/smilies/icon_e_smile","name":":icon_e_smile:","type":"Emoji","updated":"2018-09-16T11:11:11.111Z"},"to":"https://www.w3.org/ns/activitystreams#Public","type":"Note"},"published":"2018-09-25T22:35:59.770Z","to":"https://www.w3.org/ns/activitystreams#Public","type":"Create"} \ No newline at end of file
diff --git a/test/fixtures/kroeg-array-less-hashtag.json b/test/fixtures/kroeg-array-less-hashtag.json
new file mode 100644
index 000000000..28a01904c
--- /dev/null
+++ b/test/fixtures/kroeg-array-less-hashtag.json
@@ -0,0 +1 @@
+{"@context":["https://www.w3.org/ns/activitystreams","https://puckipedia.com/-/context"],"actor":"https://puckipedia.com/","id":"https://puckipedia.com/ur33-818k","object":{"attributedTo":{"endpoints":"https://puckipedia.com/#endpoints","followers":"https://puckipedia.com/followers","following":"https://puckipedia.com/following","icon":{"mediaType":"image/png","type":"Image","url":"https://puckipedia.com/images/avatar.png"},"id":"https://puckipedia.com/","inbox":"https://puckipedia.com/inbox","kroeg:blocks":{"id":"https://puckipedia.com/blocks"},"liked":"https://puckipedia.com/liked","manuallyApprovesFollowers":false,"name":"HACKER TEEN PUCKIPEDIA 👩‍💻","outbox":"https://puckipedia.com/outbox","preferredUsername":"puckipedia","publicKey":{"id":"https://puckipedia.com/#key","owner":"https://puckipedia.com/","publicKeyPem":"-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvN05xIcFE0Qgany7Rht4\n0ZI5wu++IT7K5iSqRimBYkpoeHbVcT9RFlW+aWH/QJJW/YgZ7+LMr8AMCrKrwSpS\nCndyrpx4O4lZ3FNRLu7tbklh01rGZfE6R1SFfYBpvMvImc9nYT6iezYDbv6NkHku\no3aVhjql216XlA0OhIrqQme9sAdrLbjbMrTUS8douCTkDOX+JFj1ghHCqdYEMZJI\nOY9kovtgnqyxFLm0RsPGsO1+g/OVojqG+VqHz6O2lceaTVQLlnZ4gOhLVG1tVsA2\nRfXQK+R/VgXncYE+BlQVd/tcdGAz7CDL7PP3rP65gmARnafhGR96cCOi/KzlAXSO\nMwIDAQAB\n-----END PUBLIC KEY-----","type":[]},"summary":"<p>federated hacker teen<br/>\n[<a href=\"https://pronoun.is/she\">she</a>/<a href=\"https://pronoun.is/they\">they</a>]</p>","type":"Person","updated":"2017-12-19T16:56:29.7576707+00:00"},"content":"test","id":"https://puckipedia.com/ur33-818k/note","likes":"https://puckipedia.com/ur33-818k/note/likes","replies":"https://puckipedia.com/ur33-818k/note/replies","shares":"https://puckipedia.com/ur33-818k/note/shares","tag":{"href":"https://puckipedia.com/ur33-818k/note/hashtag","id":"https://puckipedia.com/ur33-818k/note/hashtag","name":"#test","type":"Hashtag"},"to":"https://www.w3.org/ns/activitystreams#Public","type":"Note"},"to":"https://www.w3.org/ns/activitystreams#Public","type":"Create"} \ No newline at end of file
diff --git a/test/support/httpoison_mock.ex b/test/support/httpoison_mock.ex
index 7057f30fb..d8b79abef 100644
--- a/test/support/httpoison_mock.ex
+++ b/test/support/httpoison_mock.ex
@@ -404,6 +404,17 @@ defmodule HTTPoisonMock do
}}
end
+ def get("http://mastodon.example.org/users/admin/statuses/100787282858396771", _, _) do
+ {:ok,
+ %Response{
+ status_code: 200,
+ body:
+ File.read!(
+ "test/fixtures/httpoison_mock/http___mastodon.example.org_users_admin_status_1234.json"
+ )
+ }}
+ end
+
def get(
"https://pawoo.net/.well-known/webfinger",
[Accept: "application/xrd+xml,application/jrd+json"],
diff --git a/test/web/activity_pub/transmogrifier_test.exs b/test/web/activity_pub/transmogrifier_test.exs
index afa25bb60..6a6f2a44c 100644
--- a/test/web/activity_pub/transmogrifier_test.exs
+++ b/test/web/activity_pub/transmogrifier_test.exs
@@ -121,6 +121,30 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
"<p>henlo from my Psion netBook</p><p>message sent from my Psion netBook</p>"
end
+ test "it works for incoming announces with actor being inlined (kroeg)" do
+ data = File.read!("test/fixtures/kroeg-announce-with-inline-actor.json") |> Poison.decode!()
+
+ {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
+
+ assert data["actor"] == "https://puckipedia.com/"
+ end
+
+ test "it works for incoming notices with tag not being an array (kroeg)" do
+ data = File.read!("test/fixtures/kroeg-array-less-emoji.json") |> Poison.decode!()
+
+ {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
+
+ assert data["object"]["emoji"] == %{
+ "icon_e_smile" => "https://puckipedia.com/forum/images/smilies/icon_e_smile.png"
+ }
+
+ data = File.read!("test/fixtures/kroeg-array-less-hashtag.json") |> Poison.decode!()
+
+ {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
+
+ assert "test" in data["object"]["tag"]
+ end
+
test "it works for incoming follow requests" do
user = insert(:user)