implement invisible support for remote users
authorAriadne Conill <ariadne@dereferenced.org>
Sat, 5 Oct 2019 20:41:33 +0000 (20:41 +0000)
committerAriadne Conill <ariadne@dereferenced.org>
Sat, 19 Oct 2019 23:21:37 +0000 (23:21 +0000)
lib/pleroma/user/info.ex
lib/pleroma/web/activity_pub/activity_pub.ex
lib/pleroma/web/activity_pub/transmogrifier.ex
lib/pleroma/web/activity_pub/utils.ex
test/fixtures/tesla_mock/relay@mastdon.example.org.json [new file with mode: 0644]
test/support/http_request_mock.ex
test/web/activity_pub/activity_pub_test.exs

index 53525b3863f750dac87b25443d08c9b8f207fd5f..982fb61c641a783dd24674ee3ee4925c20010f36 100644 (file)
@@ -267,7 +267,8 @@ defmodule Pleroma.User.Info do
       :follower_count,
       :fields,
       :following_count,
-      :discoverable
+      :discoverable,
+      :invisible
     ])
     |> validate_fields(true)
   end
index 94c467b69e72196df67da628f450b063c22b8d05..1cfe826fad13f4bcf1ae20f3b2c5f19bd268a01a 100644 (file)
@@ -1107,6 +1107,13 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
     data = Transmogrifier.maybe_fix_user_object(data)
     discoverable = data["discoverable"] || false
 
+    invisible =
+      if is_list(data["type"]) do
+        Enum.member?(data["type"], "Invisible")
+      else
+        false
+      end
+
     user_data = %{
       ap_id: data["id"],
       info: %{
@@ -1115,7 +1122,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do
         banner: banner,
         fields: fields,
         locked: locked,
-        discoverable: discoverable
+        discoverable: discoverable,
+        invisible: invisible
       },
       avatar: avatar,
       name: data["name"],
index 2c1ce9c550fbd8983a3f253423434d1b8636dc87..49bbeb8579e490dbe436629dccbf9896ebafcc6c 100644 (file)
@@ -596,13 +596,20 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
           data,
         _options
       )
-      when object_type in ["Person", "Application", "Service", "Organization"] do
+      when object_type in [
+             "Person",
+             "Application",
+             "Service",
+             "Organization",
+             ["Application", "Invisible"]
+           ] do
     with %User{ap_id: ^actor_id} = actor <- User.get_cached_by_ap_id(object["id"]) do
       {:ok, new_user_data} = ActivityPub.user_data_from_user_object(object)
 
       banner = new_user_data[:info][:banner]
       locked = new_user_data[:info][:locked] || false
       attachment = get_in(new_user_data, [:info, :source_data, "attachment"]) || []
+      invisible = new_user_data[:info][:invisible] || false
 
       fields =
         attachment
@@ -612,7 +619,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do
       update_data =
         new_user_data
         |> Map.take([:name, :bio, :avatar])
-        |> Map.put(:info, %{banner: banner, locked: locked, fields: fields})
+        |> Map.put(:info, %{banner: banner, locked: locked, fields: fields, invisible: invisible})
 
       actor
       |> User.upgrade_changeset(update_data, true)
index 4ef479f96de5a0b81ab7dbb49bdabe238a1498d3..6b28df92c2a6ec753f233dce80cf2b8ca9b9804e 100644 (file)
@@ -491,10 +491,14 @@ defmodule Pleroma.Web.ActivityPub.Utils do
         %Activity{data: %{"actor" => actor}},
         object
       ) do
-    announcements = take_announcements(object)
+    unless actor |> User.get_cached_by_ap_id() |> User.invisible?() do
+      announcements = take_announcements(object)
 
-    with announcements <- Enum.uniq([actor | announcements]) do
-      update_element_in_object("announcement", announcements, object)
+      with announcements <- Enum.uniq([actor | announcements]) do
+        update_element_in_object("announcement", announcements, object)
+      end
+    else
+      {:ok, object}
     end
   end
 
diff --git a/test/fixtures/tesla_mock/relay@mastdon.example.org.json b/test/fixtures/tesla_mock/relay@mastdon.example.org.json
new file mode 100644 (file)
index 0000000..b70be2b
--- /dev/null
@@ -0,0 +1,54 @@
+{
+  "@context": ["https://www.w3.org/ns/activitystreams", "https://w3id.org/security/v1", {
+    "manuallyApprovesFollowers": "as:manuallyApprovesFollowers",
+    "sensitive": "as:sensitive",
+    "movedTo": "as:movedTo",
+    "Hashtag": "as:Hashtag",
+    "ostatus": "http://ostatus.org#",
+    "atomUri": "ostatus:atomUri",
+    "inReplyToAtomUri": "ostatus:inReplyToAtomUri",
+    "conversation": "ostatus:conversation",
+    "toot": "http://joinmastodon.org/ns#",
+    "Emoji": "toot:Emoji"
+  }],
+  "id": "http://mastodon.example.org/users/admin",
+  "type": ["Application", "Invisible"],
+  "following": "http://mastodon.example.org/users/admin/following",
+  "followers": "http://mastodon.example.org/users/admin/followers",
+  "inbox": "http://mastodon.example.org/users/admin/inbox",
+  "outbox": "http://mastodon.example.org/users/admin/outbox",
+  "preferredUsername": "admin",
+  "name": null,
+  "summary": "\u003cp\u003e\u003c/p\u003e",
+  "url": "http://mastodon.example.org/@admin",
+  "manuallyApprovesFollowers": false,
+  "publicKey": {
+    "id": "http://mastodon.example.org/users/admin#main-key",
+    "owner": "http://mastodon.example.org/users/admin",
+    "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtc4Tir+3ADhSNF6VKrtW\nOU32T01w7V0yshmQei38YyiVwVvFu8XOP6ACchkdxbJ+C9mZud8qWaRJKVbFTMUG\nNX4+6Q+FobyuKrwN7CEwhDALZtaN2IPbaPd6uG1B7QhWorrY+yFa8f2TBM3BxnUy\nI4T+bMIZIEYG7KtljCBoQXuTQmGtuffO0UwJksidg2ffCF5Q+K//JfQagJ3UzrR+\nZXbKMJdAw4bCVJYs4Z5EhHYBwQWiXCyMGTd7BGlmMkY6Av7ZqHKC/owp3/0EWDNz\nNqF09Wcpr3y3e8nA10X40MJqp/wR+1xtxp+YGbq/Cj5hZGBG7etFOmIpVBrDOhry\nBwIDAQAB\n-----END PUBLIC KEY-----\n"
+  },
+  "attachment": [{
+      "type": "PropertyValue",
+      "name": "foo",
+      "value": "bar"
+    },
+    {
+      "type": "PropertyValue",
+      "name": "foo1",
+      "value": "bar1"
+    }
+  ],
+  "endpoints": {
+    "sharedInbox": "http://mastodon.example.org/inbox"
+  },
+  "icon": {
+    "type": "Image",
+    "mediaType": "image/jpeg",
+    "url": "https://cdn.niu.moe/accounts/avatars/000/033/323/original/fd7f8ae0b3ffedc9.jpeg"
+  },
+  "image": {
+    "type": "Image",
+    "mediaType": "image/png",
+    "url": "https://cdn.niu.moe/accounts/headers/000/033/323/original/850b3448fa5fd477.png"
+  }
+}
index 7d65209fb1e30111595c947a83a459226158fdf4..eba22c40b1dabe5c3d09d46b00ed67a8b68423fb 100644 (file)
@@ -348,6 +348,14 @@ defmodule HttpRequestMock do
      }}
   end
 
+  def get("http://mastodon.example.org/users/relay", _, _, Accept: "application/activity+json") do
+    {:ok,
+     %Tesla.Env{
+       status: 200,
+       body: File.read!("test/fixtures/tesla_mock/relay@mastdon.example.org.json")
+     }}
+  end
+
   def get("http://mastodon.example.org/users/gargron", _, _, Accept: "application/activity+json") do
     {:error, :nxdomain}
   end
index 28a9b773c49f81a9050c81be13956dc90d04c7e2..b87050a4ac276329127c02e45119a8a15c58c346 100644 (file)
@@ -179,6 +179,12 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do
       assert user.follower_address == "http://mastodon.example.org/users/admin/followers"
     end
 
+    test "it returns a user that is invisible" do
+      user_id = "http://mastodon.example.org/users/relay"
+      {:ok, user} = ActivityPub.make_user_from_ap_id(user_id)
+      assert user.info.invisible
+    end
+
     test "it fetches the appropriate tag-restricted posts" do
       user = insert(:user)